Coverage Report

Created: 2026-04-10 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvhdi/libvhdi/libvhdi_dynamic_disk_header.c
Line
Count
Source
1
/*
2
 * Dynamic disk header functions
3
 *
4
 * Copyright (C) 2012-2025, 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 "libvhdi_debug.h"
28
#include "libvhdi_definitions.h"
29
#include "libvhdi_dynamic_disk_header.h"
30
#include "libvhdi_libbfio.h"
31
#include "libvhdi_libcerror.h"
32
#include "libvhdi_libcnotify.h"
33
#include "libvhdi_libfguid.h"
34
#include "libvhdi_libuna.h"
35
36
#include "vhdi_dynamic_disk_header.h"
37
38
/* Creates dynamic disk header
39
 * Make sure the value dynamic_disk_header is referencing, is set to NULL
40
 * Returns 1 if successful or -1 on error
41
 */
42
int libvhdi_dynamic_disk_header_initialize(
43
     libvhdi_dynamic_disk_header_t **dynamic_disk_header,
44
     libcerror_error_t **error )
45
318
{
46
318
  static char *function = "libvhdi_dynamic_disk_header_initialize";
47
48
318
  if( dynamic_disk_header == NULL )
49
0
  {
50
0
    libcerror_error_set(
51
0
     error,
52
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
53
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
54
0
     "%s: invalid dynamic disk header.",
55
0
     function );
56
57
0
    return( -1 );
58
0
  }
59
318
  if( *dynamic_disk_header != NULL )
60
0
  {
61
0
    libcerror_error_set(
62
0
     error,
63
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
64
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
65
0
     "%s: invalid dynamic disk header value already set.",
66
0
     function );
67
68
0
    return( -1 );
69
0
  }
70
318
  *dynamic_disk_header = memory_allocate_structure(
71
318
                          libvhdi_dynamic_disk_header_t );
72
73
318
  if( *dynamic_disk_header == NULL )
74
0
  {
75
0
    libcerror_error_set(
76
0
     error,
77
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
78
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
79
0
     "%s: unable to create dynamic disk header.",
80
0
     function );
81
82
0
    goto on_error;
83
0
  }
84
318
  if( memory_set(
85
318
       *dynamic_disk_header,
86
318
       0,
87
318
       sizeof( libvhdi_dynamic_disk_header_t ) ) == NULL )
88
0
  {
89
0
    libcerror_error_set(
90
0
     error,
91
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
92
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
93
0
     "%s: unable to clear dynamic disk header.",
94
0
     function );
95
96
0
    goto on_error;
97
0
  }
98
318
  return( 1 );
99
100
0
on_error:
101
0
  if( *dynamic_disk_header != NULL )
102
0
  {
103
0
    memory_free(
104
0
     *dynamic_disk_header );
105
106
0
    *dynamic_disk_header = NULL;
107
0
  }
108
0
  return( -1 );
109
318
}
110
111
/* Frees dynamic disk header
112
 * Returns 1 if successful or -1 on error
113
 */
114
int libvhdi_dynamic_disk_header_free(
115
     libvhdi_dynamic_disk_header_t **dynamic_disk_header,
116
     libcerror_error_t **error )
117
318
{
118
318
  static char *function = "libvhdi_dynamic_disk_header_free";
119
120
318
  if( dynamic_disk_header == NULL )
121
0
  {
122
0
    libcerror_error_set(
123
0
     error,
124
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
125
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
126
0
     "%s: invalid dynamic disk header.",
127
0
     function );
128
129
0
    return( -1 );
130
0
  }
131
318
  if( *dynamic_disk_header != NULL )
132
318
  {
133
318
    if( ( *dynamic_disk_header )->parent_filename != NULL )
134
86
    {
135
86
      memory_free(
136
86
       ( *dynamic_disk_header )->parent_filename );
137
86
    }
138
318
    memory_free(
139
318
     *dynamic_disk_header );
140
141
318
    *dynamic_disk_header = NULL;
142
318
  }
143
318
  return( 1 );
144
318
}
145
146
/* Reads the dynamic disk header data
147
 * Returns 1 if successful or -1 on error
148
 */
149
int libvhdi_dynamic_disk_header_read_data(
150
     libvhdi_dynamic_disk_header_t *dynamic_disk_header,
151
     const uint8_t *data,
152
     size_t data_size,
153
     libcerror_error_t **error )
154
183
{
155
183
  static char *function            = "libvhdi_dynamic_disk_header_read_data";
156
183
  size_t parent_filename_size      = 0;
157
183
  uint64_t safe_block_table_offset = 0;
158
183
  uint64_t safe_next_offset        = 0;
159
160
#if defined( HAVE_DEBUG_OUTPUT )
161
  uint32_t value_32bit             = 0;
162
#endif
163
164
183
  if( dynamic_disk_header == NULL )
165
0
  {
166
0
    libcerror_error_set(
167
0
     error,
168
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
169
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
170
0
     "%s: invalid dynamic disk header.",
171
0
     function );
172
173
0
    return( -1 );
174
0
  }
175
183
  if( dynamic_disk_header->parent_filename != NULL )
176
0
  {
177
0
    libcerror_error_set(
178
0
     error,
179
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
180
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
181
0
     "%s: invalid dynamic disk header - parent filename already set.",
182
0
     function );
183
184
0
    return( -1 );
185
0
  }
186
183
  if( data == NULL )
187
0
  {
188
0
    libcerror_error_set(
189
0
     error,
190
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
191
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
192
0
     "%s: invalid data.",
193
0
     function );
194
195
0
    return( -1 );
196
0
  }
197
183
  if( ( data_size < sizeof( vhdi_dynamic_disk_header_t ) )
198
183
   || ( data_size > (size_t) SSIZE_MAX ) )
199
0
  {
200
0
    libcerror_error_set(
201
0
     error,
202
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
203
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
204
0
     "%s: invalid data size value out of bounds.",
205
0
     function );
206
207
0
    return( -1 );
208
0
  }
209
#if defined( HAVE_DEBUG_OUTPUT )
210
  if( libcnotify_verbose != 0 )
211
  {
212
    libcnotify_printf(
213
     "%s: dynamic disk header data:\n",
214
     function );
215
    libcnotify_print_data(
216
     data,
217
     sizeof( vhdi_dynamic_disk_header_t ),
218
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
219
  }
220
#endif
221
183
  if( memory_compare(
222
183
       ( (vhdi_dynamic_disk_header_t *) data )->signature,
223
183
       "cxsparse",
224
183
       8 ) != 0 )
225
19
  {
226
19
    libcerror_error_set(
227
19
     error,
228
19
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
229
19
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
230
19
     "%s: unsupported signature.",
231
19
     function );
232
233
19
    goto on_error;
234
19
  }
235
164
  byte_stream_copy_to_uint32_big_endian(
236
164
   ( (vhdi_dynamic_disk_header_t *) data )->format_version,
237
164
   dynamic_disk_header->format_version );
238
239
164
  byte_stream_copy_to_uint64_big_endian(
240
164
   ( (vhdi_dynamic_disk_header_t *) data )->block_table_offset,
241
164
   safe_block_table_offset );
242
243
164
  dynamic_disk_header->block_table_offset = (off64_t) safe_block_table_offset;
244
245
164
  byte_stream_copy_to_uint64_big_endian(
246
164
   ( (vhdi_dynamic_disk_header_t *) data )->next_offset,
247
164
   safe_next_offset );
248
249
164
  dynamic_disk_header->next_offset = (off64_t) safe_next_offset;
250
251
164
  byte_stream_copy_to_uint32_big_endian(
252
164
   ( (vhdi_dynamic_disk_header_t *) data )->block_size,
253
164
   dynamic_disk_header->block_size );
254
255
164
  byte_stream_copy_to_uint32_big_endian(
256
164
   ( (vhdi_dynamic_disk_header_t *) data )->number_of_blocks,
257
164
   dynamic_disk_header->number_of_blocks );
258
259
164
  if( memory_copy(
260
164
       dynamic_disk_header->parent_identifier,
261
164
       ( (vhdi_dynamic_disk_header_t *) data )->parent_identifier,
262
164
       16 ) == NULL )
263
0
  {
264
0
    libcerror_error_set(
265
0
     error,
266
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
267
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
268
0
     "%s: unable to copy parent identifier.",
269
0
     function );
270
271
0
    goto on_error;
272
0
  }
273
164
  parent_filename_size = 0;
274
275
7.56k
  while( parent_filename_size < ( 512 - 1 ) )
276
7.56k
  {
277
7.56k
    if( ( ( (vhdi_dynamic_disk_header_t *) data )->parent_filename[ parent_filename_size ] == 0 )
278
1.06k
     && ( ( (vhdi_dynamic_disk_header_t *) data )->parent_filename[ parent_filename_size + 1 ] == 0 ) )
279
163
    {
280
163
      break;
281
163
    }
282
7.40k
    parent_filename_size += 2;
283
7.40k
  }
284
164
  if( parent_filename_size > 0 )
285
131
  {
286
131
    if( parent_filename_size > (size_t) ( MEMORY_MAXIMUM_ALLOCATION_SIZE - 2 ) )
287
0
    {
288
0
      libcerror_error_set(
289
0
       error,
290
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
291
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
292
0
       "%s: invalid parent filename size value exceeds maximum allocation size.",
293
0
       function );
294
295
0
      goto on_error;
296
0
    }
297
131
    parent_filename_size += 2;
298
299
131
    dynamic_disk_header->parent_filename = (uint8_t *) memory_allocate(
300
131
                                                        sizeof( uint8_t ) * parent_filename_size );
301
302
131
    if( dynamic_disk_header->parent_filename == NULL )
303
0
    {
304
0
      libcerror_error_set(
305
0
       error,
306
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
307
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
308
0
       "%s: unable to create parent filename.",
309
0
       function );
310
311
0
      goto on_error;
312
0
    }
313
131
    if( memory_copy(
314
131
         dynamic_disk_header->parent_filename,
315
131
         ( (vhdi_dynamic_disk_header_t *) data )->parent_filename,
316
131
         parent_filename_size ) == NULL )
317
0
    {
318
0
      libcerror_error_set(
319
0
       error,
320
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
321
0
       LIBCERROR_MEMORY_ERROR_COPY_FAILED,
322
0
       "%s: unable to copy parent filename.",
323
0
       function );
324
325
0
      goto on_error;
326
0
    }
327
131
  }
328
164
  dynamic_disk_header->parent_filename_size = parent_filename_size;
329
330
#if defined( HAVE_DEBUG_OUTPUT )
331
  if( libcnotify_verbose != 0 )
332
  {
333
    libcnotify_printf(
334
     "%s: signature\t\t\t: %c%c%c%c%c%c%c%c\n",
335
     function,
336
     ( (vhdi_dynamic_disk_header_t *) data )->signature[ 0 ],
337
     ( (vhdi_dynamic_disk_header_t *) data )->signature[ 1 ],
338
     ( (vhdi_dynamic_disk_header_t *) data )->signature[ 2 ],
339
     ( (vhdi_dynamic_disk_header_t *) data )->signature[ 3 ],
340
     ( (vhdi_dynamic_disk_header_t *) data )->signature[ 4 ],
341
     ( (vhdi_dynamic_disk_header_t *) data )->signature[ 5 ],
342
     ( (vhdi_dynamic_disk_header_t *) data )->signature[ 6 ],
343
     ( (vhdi_dynamic_disk_header_t *) data )->signature[ 7 ] );
344
345
    libcnotify_printf(
346
     "%s: format version\t\t\t: %" PRIu16 ".%" PRIu16 "\n",
347
     function,
348
     dynamic_disk_header->format_version >> 16,
349
     dynamic_disk_header->format_version & 0x0000ffffUL );
350
351
    libcnotify_printf(
352
     "%s: block table offset\t\t: 0x%08" PRIx64 "\n",
353
     function,
354
     safe_block_table_offset );
355
356
    libcnotify_printf(
357
     "%s: next offset\t\t\t: 0x%08" PRIx64 "\n",
358
     function,
359
     safe_next_offset );
360
361
    libcnotify_printf(
362
     "%s: block size\t\t\t: %" PRIu64 "\n",
363
     function,
364
     dynamic_disk_header->block_size );
365
366
    libcnotify_printf(
367
     "%s: number of blocks\t\t\t: %" PRIu64 "\n",
368
     function,
369
     dynamic_disk_header->number_of_blocks );
370
371
    byte_stream_copy_to_uint32_big_endian(
372
     ( (vhdi_dynamic_disk_header_t *) data )->checksum,
373
     value_32bit );
374
    libcnotify_printf(
375
     "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
376
     function,
377
     value_32bit );
378
379
    if( libvhdi_debug_print_guid_value(
380
         function,
381
         "parent identifier\t\t",
382
         ( (vhdi_dynamic_disk_header_t *) data )->parent_identifier,
383
         16,
384
         LIBFGUID_ENDIAN_BIG,
385
         LIBFGUID_STRING_FORMAT_FLAG_USE_LOWER_CASE,
386
         error ) != 1 )
387
    {
388
      libcerror_error_set(
389
       error,
390
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
391
       LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
392
       "%s: unable to print GUID value.",
393
       function );
394
395
      goto on_error;
396
    }
397
    byte_stream_copy_to_uint32_big_endian(
398
     ( (vhdi_dynamic_disk_header_t *) data )->parent_modification_time,
399
     value_32bit );
400
    libcnotify_printf(
401
     "%s: parent modification time\t\t: 0x%08" PRIx32 "\n",
402
     function,
403
     value_32bit );
404
405
    libcnotify_printf(
406
     "%s: parent filename data:\n",
407
     function );
408
    libcnotify_print_data(
409
     ( (vhdi_dynamic_disk_header_t *) data )->parent_filename,
410
     512,
411
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
412
413
    if( dynamic_disk_header->parent_filename_size > 0 )
414
    {
415
      if( libvhdi_debug_print_utf16_string_value(
416
           function,
417
           "parent filename\t\t\t",
418
           dynamic_disk_header->parent_filename,
419
           dynamic_disk_header->parent_filename_size,
420
           LIBUNA_ENDIAN_BIG,
421
           error ) != 1 )
422
      {
423
        libcerror_error_set(
424
         error,
425
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
426
         LIBCERROR_RUNTIME_ERROR_PRINT_FAILED,
427
         "%s: unable to print UTF-16 string value.",
428
         function );
429
430
        goto on_error;
431
      }
432
    }
433
    libcnotify_printf(
434
     "%s: parent locator entries data:\n",
435
     function );
436
    libcnotify_print_data(
437
     ( (vhdi_dynamic_disk_header_t *) data )->parent_locator_entries,
438
     192,
439
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
440
441
    libcnotify_printf(
442
     "%s: unknown2:\n",
443
     function );
444
    libcnotify_print_data(
445
     ( (vhdi_dynamic_disk_header_t *) data )->unknown2,
446
     256,
447
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
448
  }
449
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
450
451
164
  if( dynamic_disk_header->format_version != 0x00010000UL )
452
40
  {
453
40
    libcerror_error_set(
454
40
     error,
455
40
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
456
40
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
457
40
     "%s: unsupported format version: 0x%08" PRIx32 ".",
458
40
     function,
459
40
     dynamic_disk_header->format_version );
460
461
40
    goto on_error;
462
40
  }
463
124
  if( dynamic_disk_header->block_size == 0 )
464
1
  {
465
1
    libcerror_error_set(
466
1
     error,
467
1
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
468
1
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
469
1
     "%s: invalid block size value out of bounds.",
470
1
     function );
471
472
1
    goto on_error;
473
1
  }
474
/* TODO check if block size is power of 2 */
475
123
  if( ( dynamic_disk_header->block_size % 512 ) != 0 )
476
15
  {
477
15
    libcerror_error_set(
478
15
     error,
479
15
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
480
15
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
481
15
     "%s: unsupported block size: %" PRIu32 ".",
482
15
     function,
483
15
     dynamic_disk_header->block_size );
484
485
15
    goto on_error;
486
15
  }
487
108
  return( 1 );
488
489
75
on_error:
490
75
  if( dynamic_disk_header->parent_filename != NULL )
491
45
  {
492
45
    memory_free(
493
45
     dynamic_disk_header->parent_filename );
494
495
45
    dynamic_disk_header->parent_filename = NULL;
496
45
  }
497
75
  dynamic_disk_header->parent_filename_size = 0;
498
499
75
  return( -1 );
500
123
}
501
502
/* Reads the dynamic disk header
503
 * Returns 1 if successful or -1 on error
504
 */
505
int libvhdi_dynamic_disk_header_read_file_io_handle(
506
     libvhdi_dynamic_disk_header_t *dynamic_disk_header,
507
     libbfio_handle_t *file_io_handle,
508
     off64_t file_offset,
509
     libcerror_error_t **error )
510
318
{
511
318
  uint8_t dynamic_disk_header_data[ sizeof( vhdi_dynamic_disk_header_t ) ];
512
513
318
  static char *function = "libvhdi_dynamic_disk_header_read_file_io_handle";
514
318
  ssize_t read_count    = 0;
515
516
318
  if( dynamic_disk_header == NULL )
517
0
  {
518
0
    libcerror_error_set(
519
0
     error,
520
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
521
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
522
0
     "%s: invalid dynamic disk header.",
523
0
     function );
524
525
0
    return( -1 );
526
0
  }
527
#if defined( HAVE_DEBUG_OUTPUT )
528
  if( libcnotify_verbose != 0 )
529
  {
530
    libcnotify_printf(
531
     "%s: reading dynamic disk header at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
532
     function,
533
     file_offset,
534
     file_offset );
535
  }
536
#endif
537
318
  read_count = libbfio_handle_read_buffer_at_offset(
538
318
                file_io_handle,
539
318
                dynamic_disk_header_data,
540
318
                sizeof( vhdi_dynamic_disk_header_t ),
541
318
                file_offset,
542
318
                error );
543
544
318
  if( read_count != (ssize_t) sizeof( vhdi_dynamic_disk_header_t ) )
545
135
  {
546
135
    libcerror_error_set(
547
135
     error,
548
135
     LIBCERROR_ERROR_DOMAIN_IO,
549
135
     LIBCERROR_IO_ERROR_READ_FAILED,
550
135
     "%s: unable to read dynamic disk header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
551
135
     function,
552
135
     file_offset,
553
135
     file_offset );
554
555
135
    return( -1 );
556
135
  }
557
183
  if( libvhdi_dynamic_disk_header_read_data(
558
183
       dynamic_disk_header,
559
183
       dynamic_disk_header_data,
560
183
       sizeof( vhdi_dynamic_disk_header_t ),
561
183
       error ) != 1 )
562
75
  {
563
75
    libcerror_error_set(
564
75
     error,
565
75
     LIBCERROR_ERROR_DOMAIN_IO,
566
75
     LIBCERROR_IO_ERROR_READ_FAILED,
567
75
     "%s: unable to read dynamic disk header.",
568
75
     function );
569
570
75
    return( -1 );
571
75
  }
572
108
  return( 1 );
573
183
}
574
575
/* Retrieves the parent identifier
576
 * Returns 1 if successful or -1 on error
577
 */
578
int libvhdi_dynamic_disk_header_get_parent_identifier(
579
     libvhdi_dynamic_disk_header_t *dynamic_disk_header,
580
     uint8_t *guid_data,
581
     size_t guid_data_size,
582
     libcerror_error_t **error )
583
0
{
584
0
  static char *function = "libvhdi_dynamic_disk_header_get_parent_identifier";
585
586
0
  if( dynamic_disk_header == NULL )
587
0
  {
588
0
    libcerror_error_set(
589
0
     error,
590
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
591
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
592
0
     "%s: invalid dynamic disk header.",
593
0
     function );
594
595
0
    return( -1 );
596
0
  }
597
0
  if( guid_data == NULL )
598
0
  {
599
0
    libcerror_error_set(
600
0
     error,
601
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
602
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
603
0
     "%s: invalid GUID data.",
604
0
     function );
605
606
0
    return( -1 );
607
0
  }
608
0
  if( ( guid_data_size < 16 )
609
0
   || ( guid_data_size > (size_t) SSIZE_MAX ) )
610
0
  {
611
0
    libcerror_error_set(
612
0
     error,
613
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
614
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
615
0
     "%s: invalid GUID data size value out of bounds.",
616
0
     function );
617
618
0
    return( -1 );
619
0
  }
620
0
  if( memory_copy(
621
0
       guid_data,
622
0
       dynamic_disk_header->parent_identifier,
623
0
       16 ) == NULL )
624
0
  {
625
0
    libcerror_error_set(
626
0
     error,
627
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
628
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
629
0
     "%s: unable to copy parent identifier.",
630
0
     function );
631
632
0
    return( -1 );
633
0
  }
634
0
  return( 1 );
635
0
}
636
637
/* Retrieves the size of the UTF-8 encoded parent filename
638
 * The returned size includes the end of string character
639
 * Returns 1 if successful, 0 if not available or -1 on error
640
 */
641
int libvhdi_dynamic_disk_header_get_utf8_parent_filename_size(
642
     libvhdi_dynamic_disk_header_t *dynamic_disk_header,
643
     size_t *utf8_string_size,
644
     libcerror_error_t **error )
645
0
{
646
0
  static char *function = "libvhdi_dynamic_disk_header_get_utf8_parent_filename_size";
647
0
  int result            = 0;
648
649
0
  if( dynamic_disk_header == NULL )
650
0
  {
651
0
    libcerror_error_set(
652
0
     error,
653
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
654
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
655
0
     "%s: invalid dynamic disk header.",
656
0
     function );
657
658
0
    return( -1 );
659
0
  }
660
0
  if( ( dynamic_disk_header->parent_filename != NULL )
661
0
   && ( dynamic_disk_header->parent_filename_size > 0 ) )
662
0
  {
663
0
    result = libuna_utf8_string_size_from_utf16_stream(
664
0
              dynamic_disk_header->parent_filename,
665
0
              dynamic_disk_header->parent_filename_size,
666
0
              LIBUNA_ENDIAN_BIG,
667
0
              utf8_string_size,
668
0
              error );
669
670
0
    if( result != 1 )
671
0
    {
672
0
      libcerror_error_set(
673
0
       error,
674
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
675
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
676
0
       "%s: unable to retrieve UTF-8 string size.",
677
0
       function );
678
679
0
      return( -1 );
680
0
    }
681
0
  }
682
0
  return( result );
683
0
}
684
685
/* Retrieves the UTF-8 encoded parent filename
686
 * The size should include the end of string character
687
 * Returns 1 if successful, 0 if not available or -1 on error
688
 */
689
int libvhdi_dynamic_disk_header_get_utf8_parent_filename(
690
     libvhdi_dynamic_disk_header_t *dynamic_disk_header,
691
     uint8_t *utf8_string,
692
     size_t utf8_string_size,
693
     libcerror_error_t **error )
694
0
{
695
0
  static char *function = "libvhdi_dynamic_disk_header_get_utf8_parent_filename";
696
0
  int result            = 0;
697
698
0
  if( dynamic_disk_header == NULL )
699
0
  {
700
0
    libcerror_error_set(
701
0
     error,
702
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
703
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
704
0
     "%s: invalid dynamic disk header.",
705
0
     function );
706
707
0
    return( -1 );
708
0
  }
709
0
  if( ( dynamic_disk_header->parent_filename != NULL )
710
0
   && ( dynamic_disk_header->parent_filename_size > 0 ) )
711
0
  {
712
0
    result = libuna_utf8_string_copy_from_utf16_stream(
713
0
              utf8_string,
714
0
              utf8_string_size,
715
0
              dynamic_disk_header->parent_filename,
716
0
              dynamic_disk_header->parent_filename_size,
717
0
              LIBUNA_ENDIAN_BIG,
718
0
              error );
719
720
0
    if( result != 1 )
721
0
    {
722
0
      libcerror_error_set(
723
0
       error,
724
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
725
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
726
0
       "%s: unable to copy parent filename to UTF-8 string.",
727
0
       function );
728
729
0
      return( -1 );
730
0
    }
731
0
  }
732
0
  return( result );
733
0
}
734
735
/* Retrieves the size of the UTF-16 encoded parent filename
736
 * The returned size includes the end of string character
737
 * Returns 1 if successful, 0 if not available or -1 on error
738
 */
739
int libvhdi_dynamic_disk_header_get_utf16_parent_filename_size(
740
     libvhdi_dynamic_disk_header_t *dynamic_disk_header,
741
     size_t *utf16_string_size,
742
     libcerror_error_t **error )
743
0
{
744
0
  static char *function = "libvhdi_dynamic_disk_header_get_utf16_parent_filename_size";
745
0
  int result            = 0;
746
747
0
  if( dynamic_disk_header == NULL )
748
0
  {
749
0
    libcerror_error_set(
750
0
     error,
751
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
752
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
753
0
     "%s: invalid dynamic disk header.",
754
0
     function );
755
756
0
    return( -1 );
757
0
  }
758
0
  if( ( dynamic_disk_header->parent_filename != NULL )
759
0
   && ( dynamic_disk_header->parent_filename_size > 0 ) )
760
0
  {
761
0
    result = libuna_utf16_string_size_from_utf16_stream(
762
0
              dynamic_disk_header->parent_filename,
763
0
              dynamic_disk_header->parent_filename_size,
764
0
              LIBUNA_ENDIAN_BIG,
765
0
              utf16_string_size,
766
0
              error );
767
768
0
    if( result != 1 )
769
0
    {
770
0
      libcerror_error_set(
771
0
       error,
772
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
773
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
774
0
       "%s: unable to retrieve UTF-16 string size.",
775
0
       function );
776
777
0
      return( -1 );
778
0
    }
779
0
  }
780
0
  return( result );
781
0
}
782
783
/* Retrieves the UTF-16 encoded parent filename
784
 * The size should include the end of string character
785
 * Returns 1 if successful, 0 if not available or -1 on error
786
 */
787
int libvhdi_dynamic_disk_header_get_utf16_parent_filename(
788
     libvhdi_dynamic_disk_header_t *dynamic_disk_header,
789
     uint16_t *utf16_string,
790
     size_t utf16_string_size,
791
     libcerror_error_t **error )
792
0
{
793
0
  static char *function = "libvhdi_dynamic_disk_header_get_utf16_parent_filename";
794
0
  int result            = 0;
795
796
0
  if( dynamic_disk_header == NULL )
797
0
  {
798
0
    libcerror_error_set(
799
0
     error,
800
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
801
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
802
0
     "%s: invalid dynamic disk header.",
803
0
     function );
804
805
0
    return( -1 );
806
0
  }
807
0
  if( ( dynamic_disk_header->parent_filename != NULL )
808
0
   && ( dynamic_disk_header->parent_filename_size > 0 ) )
809
0
  {
810
0
    result = libuna_utf16_string_copy_from_utf16_stream(
811
0
              utf16_string,
812
0
              utf16_string_size,
813
0
              dynamic_disk_header->parent_filename,
814
0
              dynamic_disk_header->parent_filename_size,
815
0
              LIBUNA_ENDIAN_BIG,
816
0
              error );
817
818
0
    if( result != 1 )
819
0
    {
820
0
      libcerror_error_set(
821
0
       error,
822
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
823
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
824
0
       "%s: unable to copy parent filename to UTF-16 string.",
825
0
       function );
826
827
0
      return( -1 );
828
0
    }
829
0
  }
830
0
  return( result );
831
0
}
832