Coverage Report

Created: 2026-01-20 07:11

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
289
{
46
289
  static char *function = "libvhdi_dynamic_disk_header_initialize";
47
48
289
  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
289
  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
289
  *dynamic_disk_header = memory_allocate_structure(
71
289
                          libvhdi_dynamic_disk_header_t );
72
73
289
  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
289
  if( memory_set(
85
289
       *dynamic_disk_header,
86
289
       0,
87
289
       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
289
  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
289
}
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
289
{
118
289
  static char *function = "libvhdi_dynamic_disk_header_free";
119
120
289
  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
289
  if( *dynamic_disk_header != NULL )
132
289
  {
133
289
    if( ( *dynamic_disk_header )->parent_filename != NULL )
134
69
    {
135
69
      memory_free(
136
69
       ( *dynamic_disk_header )->parent_filename );
137
69
    }
138
289
    memory_free(
139
289
     *dynamic_disk_header );
140
141
289
    *dynamic_disk_header = NULL;
142
289
  }
143
289
  return( 1 );
144
289
}
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
164
{
155
164
  static char *function            = "libvhdi_dynamic_disk_header_read_data";
156
164
  size_t parent_filename_size      = 0;
157
164
  uint64_t safe_block_table_offset = 0;
158
164
  uint64_t safe_next_offset        = 0;
159
160
#if defined( HAVE_DEBUG_OUTPUT )
161
  uint32_t value_32bit             = 0;
162
#endif
163
164
164
  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
164
  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
164
  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
164
  if( ( data_size < sizeof( vhdi_dynamic_disk_header_t ) )
198
164
   || ( 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
164
  if( memory_compare(
222
164
       ( (vhdi_dynamic_disk_header_t *) data )->signature,
223
164
       "cxsparse",
224
164
       8 ) != 0 )
225
18
  {
226
18
    libcerror_error_set(
227
18
     error,
228
18
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
229
18
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
230
18
     "%s: unsupported signature.",
231
18
     function );
232
233
18
    goto on_error;
234
18
  }
235
146
  byte_stream_copy_to_uint32_big_endian(
236
146
   ( (vhdi_dynamic_disk_header_t *) data )->format_version,
237
146
   dynamic_disk_header->format_version );
238
239
146
  byte_stream_copy_to_uint64_big_endian(
240
146
   ( (vhdi_dynamic_disk_header_t *) data )->block_table_offset,
241
146
   safe_block_table_offset );
242
243
146
  dynamic_disk_header->block_table_offset = (off64_t) safe_block_table_offset;
244
245
146
  byte_stream_copy_to_uint64_big_endian(
246
146
   ( (vhdi_dynamic_disk_header_t *) data )->next_offset,
247
146
   safe_next_offset );
248
249
146
  dynamic_disk_header->next_offset = (off64_t) safe_next_offset;
250
251
146
  byte_stream_copy_to_uint32_big_endian(
252
146
   ( (vhdi_dynamic_disk_header_t *) data )->block_size,
253
146
   dynamic_disk_header->block_size );
254
255
146
  byte_stream_copy_to_uint32_big_endian(
256
146
   ( (vhdi_dynamic_disk_header_t *) data )->number_of_blocks,
257
146
   dynamic_disk_header->number_of_blocks );
258
259
146
  if( memory_copy(
260
146
       dynamic_disk_header->parent_identifier,
261
146
       ( (vhdi_dynamic_disk_header_t *) data )->parent_identifier,
262
146
       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
146
  parent_filename_size = 0;
274
275
4.42k
  while( parent_filename_size < ( 512 - 1 ) )
276
4.42k
  {
277
4.42k
    if( ( ( (vhdi_dynamic_disk_header_t *) data )->parent_filename[ parent_filename_size ] == 0 )
278
706
     && ( ( (vhdi_dynamic_disk_header_t *) data )->parent_filename[ parent_filename_size + 1 ] == 0 ) )
279
145
    {
280
145
      break;
281
145
    }
282
4.28k
    parent_filename_size += 2;
283
4.28k
  }
284
146
  if( parent_filename_size > 0 )
285
111
  {
286
111
    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
111
    parent_filename_size += 2;
298
299
111
    dynamic_disk_header->parent_filename = (uint8_t *) memory_allocate(
300
111
                                                        sizeof( uint8_t ) * parent_filename_size );
301
302
111
    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
111
    if( memory_copy(
314
111
         dynamic_disk_header->parent_filename,
315
111
         ( (vhdi_dynamic_disk_header_t *) data )->parent_filename,
316
111
         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
111
  }
328
146
  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
146
  if( dynamic_disk_header->format_version != 0x00010000UL )
452
39
  {
453
39
    libcerror_error_set(
454
39
     error,
455
39
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
456
39
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
457
39
     "%s: unsupported format version: 0x%08" PRIx32 ".",
458
39
     function,
459
39
     dynamic_disk_header->format_version );
460
461
39
    goto on_error;
462
39
  }
463
107
  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
106
  if( ( dynamic_disk_header->block_size % 512 ) != 0 )
476
10
  {
477
10
    libcerror_error_set(
478
10
     error,
479
10
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
480
10
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
481
10
     "%s: unsupported block size: %" PRIu32 ".",
482
10
     function,
483
10
     dynamic_disk_header->block_size );
484
485
10
    goto on_error;
486
10
  }
487
96
  return( 1 );
488
489
68
on_error:
490
68
  if( dynamic_disk_header->parent_filename != NULL )
491
42
  {
492
42
    memory_free(
493
42
     dynamic_disk_header->parent_filename );
494
495
42
    dynamic_disk_header->parent_filename = NULL;
496
42
  }
497
68
  dynamic_disk_header->parent_filename_size = 0;
498
499
68
  return( -1 );
500
106
}
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
289
{
511
289
  uint8_t dynamic_disk_header_data[ sizeof( vhdi_dynamic_disk_header_t ) ];
512
513
289
  static char *function = "libvhdi_dynamic_disk_header_read_file_io_handle";
514
289
  ssize_t read_count    = 0;
515
516
289
  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
289
  read_count = libbfio_handle_read_buffer_at_offset(
538
289
                file_io_handle,
539
289
                dynamic_disk_header_data,
540
289
                sizeof( vhdi_dynamic_disk_header_t ),
541
289
                file_offset,
542
289
                error );
543
544
289
  if( read_count != (ssize_t) sizeof( vhdi_dynamic_disk_header_t ) )
545
125
  {
546
125
    libcerror_error_set(
547
125
     error,
548
125
     LIBCERROR_ERROR_DOMAIN_IO,
549
125
     LIBCERROR_IO_ERROR_READ_FAILED,
550
125
     "%s: unable to read dynamic disk header data at offset: %" PRIi64 " (0x%08" PRIx64 ").",
551
125
     function,
552
125
     file_offset,
553
125
     file_offset );
554
555
125
    return( -1 );
556
125
  }
557
164
  if( libvhdi_dynamic_disk_header_read_data(
558
164
       dynamic_disk_header,
559
164
       dynamic_disk_header_data,
560
164
       sizeof( vhdi_dynamic_disk_header_t ),
561
164
       error ) != 1 )
562
68
  {
563
68
    libcerror_error_set(
564
68
     error,
565
68
     LIBCERROR_ERROR_DOMAIN_IO,
566
68
     LIBCERROR_IO_ERROR_READ_FAILED,
567
68
     "%s: unable to read dynamic disk header.",
568
68
     function );
569
570
68
    return( -1 );
571
68
  }
572
96
  return( 1 );
573
164
}
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