Coverage Report

Created: 2025-08-28 07:10

/src/libcreg/libcreg/libcreg_key_navigation.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Key navigation functions
3
 *
4
 * Copyright (C) 2013-2024, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libcreg_data_block.h"
28
#include "libcreg_definitions.h"
29
#include "libcreg_io_handle.h"
30
#include "libcreg_key_name_entry.h"
31
#include "libcreg_key_navigation.h"
32
#include "libcreg_libbfio.h"
33
#include "libcreg_libcerror.h"
34
#include "libcreg_libcnotify.h"
35
#include "libcreg_libfcache.h"
36
#include "libcreg_libfdata.h"
37
#include "libcreg_unused.h"
38
39
#include "creg_file_header.h"
40
#include "creg_key_navigation.h"
41
42
const char *creg_key_navigation_signature = "RGKN";
43
44
/* Creates a key navigation
45
 * Make sure the value key_navigation is referencing, is set to NULL
46
 * Returns 1 if successful or -1 on error
47
 */
48
int libcreg_key_navigation_initialize(
49
     libcreg_key_navigation_t **key_navigation,
50
     libcreg_io_handle_t *io_handle,
51
     libcerror_error_t **error )
52
2.62k
{
53
2.62k
  static char *function = "libcreg_key_navigation_initialize";
54
55
2.62k
  if( key_navigation == NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
60
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
61
0
     "%s: invalid key navigation.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
2.62k
  if( *key_navigation != NULL )
67
0
  {
68
0
    libcerror_error_set(
69
0
     error,
70
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
71
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
72
0
     "%s: invalid key navigation value already set.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
2.62k
  *key_navigation = memory_allocate_structure(
78
2.62k
                     libcreg_key_navigation_t );
79
80
2.62k
  if( *key_navigation == NULL )
81
0
  {
82
0
    libcerror_error_set(
83
0
     error,
84
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
85
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
86
0
     "%s: unable to create key navigation.",
87
0
     function );
88
89
0
    goto on_error;
90
0
  }
91
2.62k
  if( memory_set(
92
2.62k
       *key_navigation,
93
2.62k
       0,
94
2.62k
       sizeof( libcreg_key_navigation_t ) ) == NULL )
95
0
  {
96
0
    libcerror_error_set(
97
0
     error,
98
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
99
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
100
0
     "%s: unable to clear key navigation.",
101
0
     function );
102
103
0
    goto on_error;
104
0
  }
105
2.62k
  ( *key_navigation )->io_handle = io_handle;
106
107
2.62k
  return( 1 );
108
109
0
on_error:
110
0
  if( *key_navigation != NULL )
111
0
  {
112
0
    memory_free(
113
0
     *key_navigation );
114
115
0
    *key_navigation = NULL;
116
0
  }
117
0
  return( -1 );
118
2.62k
}
119
120
/* Frees a key navigation
121
 * Returns 1 if successful or -1 on error
122
 */
123
int libcreg_key_navigation_free(
124
     libcreg_key_navigation_t **key_navigation,
125
     libcerror_error_t **error )
126
2.62k
{
127
2.62k
  static char *function = "libcreg_key_navigation_free";
128
2.62k
  int result            = 1;
129
130
2.62k
  if( key_navigation == NULL )
131
0
  {
132
0
    libcerror_error_set(
133
0
     error,
134
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
135
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
136
0
     "%s: invalid key navigation.",
137
0
     function );
138
139
0
    return( -1 );
140
0
  }
141
2.62k
  if( *key_navigation != NULL )
142
2.62k
  {
143
    /* The io_handle reference is freed elsewhere
144
     */
145
2.62k
    if( ( *key_navigation )->key_hierarchy_area != NULL )
146
2.04k
    {
147
2.04k
      if( libfdata_area_free(
148
2.04k
           &( ( *key_navigation )->key_hierarchy_area ),
149
2.04k
           error ) != 1 )
150
0
      {
151
0
        libcerror_error_set(
152
0
         error,
153
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
154
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
155
0
         "%s: unable to free key hierarchy area.",
156
0
         function );
157
158
0
        result = -1;
159
0
      }
160
2.04k
    }
161
2.62k
    if( ( *key_navigation )->key_hierarchy_cache != NULL )
162
2.04k
    {
163
2.04k
      if( libfcache_cache_free(
164
2.04k
           &( ( *key_navigation )->key_hierarchy_cache ),
165
2.04k
           error ) != 1 )
166
0
      {
167
0
        libcerror_error_set(
168
0
         error,
169
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
170
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
171
0
         "%s: unable to free key hierarchy cache.",
172
0
         function );
173
174
0
        result = -1;
175
0
      }
176
2.04k
    }
177
2.62k
    if( ( *key_navigation )->data_blocks_list != NULL )
178
2.26k
    {
179
2.26k
      if( libfdata_list_free(
180
2.26k
           &( ( *key_navigation )->data_blocks_list ),
181
2.26k
           error ) != 1 )
182
0
      {
183
0
        libcerror_error_set(
184
0
         error,
185
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
186
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
187
0
         "%s: unable to free data blocks list.",
188
0
         function );
189
190
0
        result = -1;
191
0
      }
192
2.26k
    }
193
2.62k
    if( ( *key_navigation )->data_blocks_cache != NULL )
194
2.26k
    {
195
2.26k
      if( libfcache_cache_free(
196
2.26k
           &( ( *key_navigation )->data_blocks_cache ),
197
2.26k
           error ) != 1 )
198
0
      {
199
0
        libcerror_error_set(
200
0
         error,
201
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
202
0
         LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
203
0
         "%s: unable to free data blocks cache.",
204
0
         function );
205
206
0
        result = -1;
207
0
      }
208
2.26k
    }
209
2.62k
    memory_free(
210
2.62k
     *key_navigation );
211
212
2.62k
    *key_navigation = NULL;
213
2.62k
  }
214
2.62k
  return( result );
215
2.62k
}
216
217
/* Reads a key navigation record
218
 * Returns 1 if successful, 0 if no key navigation signature was found or -1 on error
219
 */
220
int libcreg_key_navigation_read_file_io_handle(
221
     libcreg_key_navigation_t *key_navigation,
222
     libbfio_handle_t *file_io_handle,
223
     libcerror_error_t **error )
224
2.62k
{
225
2.62k
  creg_key_navigation_header_t key_navigation_header;
226
227
2.62k
  static char *function                      = "libcreg_key_navigation_read_file_io_handle";
228
2.62k
  ssize_t read_count                         = 0;
229
2.62k
  uint32_t data_size                         = 0;
230
2.62k
  uint32_t key_hierarchy_entries_data_offset = 0;
231
2.62k
  int entry_index                            = 0;
232
233
#if defined( HAVE_DEBUG_OUTPUT )
234
  uint32_t value_32bit                       = 0;
235
#endif
236
237
2.62k
  if( key_navigation == NULL )
238
0
  {
239
0
    libcerror_error_set(
240
0
     error,
241
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
242
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
243
0
     "%s: invalid key navigation.",
244
0
     function );
245
246
0
    return( -1 );
247
0
  }
248
2.62k
  if( key_navigation->key_hierarchy_area != NULL )
249
0
  {
250
0
    libcerror_error_set(
251
0
     error,
252
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
253
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
254
0
     "%s: invalid key navigation - key hierarchy area already set.",
255
0
     function );
256
257
0
    return( -1 );
258
0
  }
259
2.62k
  if( key_navigation->key_hierarchy_cache != NULL )
260
0
  {
261
0
    libcerror_error_set(
262
0
     error,
263
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
264
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
265
0
     "%s: invalid key navigation - key hierarchy cache already set.",
266
0
     function );
267
268
0
    return( -1 );
269
0
  }
270
#if defined( HAVE_DEBUG_OUTPUT )
271
  if( libcnotify_verbose != 0 )
272
  {
273
    libcnotify_printf(
274
     "%s: reading key navigation at offset: %" PRIzd " (0x%08" PRIzx ")\n",
275
     function,
276
     sizeof( creg_file_header_t ),
277
     sizeof( creg_file_header_t ) );
278
  }
279
#endif
280
2.62k
  read_count = libbfio_handle_read_buffer(
281
2.62k
                file_io_handle,
282
2.62k
                (uint8_t *) &key_navigation_header,
283
2.62k
                sizeof( creg_key_navigation_header_t ),
284
2.62k
                error );
285
286
2.62k
  if( read_count != (ssize_t) sizeof( creg_key_navigation_header_t ) )
287
29
  {
288
29
    libcerror_error_set(
289
29
     error,
290
29
     LIBCERROR_ERROR_DOMAIN_IO,
291
29
     LIBCERROR_IO_ERROR_READ_FAILED,
292
29
     "%s: unable to read key navigation header data.",
293
29
     function );
294
295
29
    goto on_error;
296
29
  }
297
#if defined( HAVE_DEBUG_OUTPUT )
298
  if( libcnotify_verbose != 0 )
299
  {
300
    libcnotify_printf(
301
     "%s: key navigation header:\n",
302
     function );
303
    libcnotify_print_data(
304
     (uint8_t *) &key_navigation_header,
305
     sizeof( creg_key_navigation_header_t ),
306
     0 );
307
  }
308
#endif
309
2.59k
  if( memory_compare(
310
2.59k
       key_navigation_header.signature,
311
2.59k
       creg_key_navigation_signature,
312
2.59k
       4 ) != 0 )
313
535
  {
314
535
    return( 0 );
315
535
  }
316
2.06k
  byte_stream_copy_to_uint32_little_endian(
317
2.06k
   key_navigation_header.size,
318
2.06k
   data_size );
319
320
2.06k
  byte_stream_copy_to_uint32_little_endian(
321
2.06k
   key_navigation_header.key_hierarchy_entries_data_offset,
322
2.06k
   key_hierarchy_entries_data_offset );
323
324
#if defined( HAVE_DEBUG_OUTPUT )
325
  if( libcnotify_verbose != 0 )
326
  {
327
    libcnotify_printf(
328
     "%s: signature\t\t\t\t: %c%c%c%c\n",
329
     function,
330
     key_navigation_header.signature[ 0 ],
331
     key_navigation_header.signature[ 1 ],
332
     key_navigation_header.signature[ 2 ],
333
     key_navigation_header.signature[ 3 ] );
334
335
    libcnotify_printf(
336
     "%s: size\t\t\t\t: %" PRIu32 "\n",
337
     function,
338
     data_size );
339
340
    libcnotify_printf(
341
     "%s: key hierarchy entries data offset\t: 0x%08" PRIx32 "\n",
342
     function,
343
     key_hierarchy_entries_data_offset );
344
345
    byte_stream_copy_to_uint32_little_endian(
346
     key_navigation_header.unknown2,
347
     value_32bit );
348
    libcnotify_printf(
349
     "%s: unknown2\t\t\t\t: 0x%08" PRIx32 "\n",
350
     function,
351
     value_32bit );
352
353
    byte_stream_copy_to_uint32_little_endian(
354
     key_navigation_header.unknown3,
355
     value_32bit );
356
    libcnotify_printf(
357
     "%s: unknown3\t\t\t\t: 0x%08" PRIx32 "\n",
358
     function,
359
     value_32bit );
360
361
    byte_stream_copy_to_uint32_little_endian(
362
     key_navigation_header.unknown4,
363
     value_32bit );
364
    libcnotify_printf(
365
     "%s: unknown4\t\t\t\t: 0x%08" PRIx32 "\n",
366
     function,
367
     value_32bit );
368
369
    libcnotify_printf(
370
     "%s: unknown5:\n",
371
     function );
372
    libcnotify_print_data(
373
     key_navigation_header.unknown5,
374
     8,
375
     0 );
376
  }
377
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
378
379
2.06k
  if( data_size < sizeof( creg_key_navigation_header_t ) )
380
16
  {
381
16
    libcerror_error_set(
382
16
     error,
383
16
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
384
16
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
385
16
     "%s: invalid data size value out of bounds.",
386
16
     function );
387
388
16
    goto on_error;
389
16
  }
390
#if SIZEOF_SIZE_T <= 4
391
  if( data_size > (size_t) SSIZE_MAX )
392
#else
393
2.04k
  if( data_size > (uint32_t) SSIZE_MAX )
394
0
#endif
395
0
  {
396
0
    libcerror_error_set(
397
0
     error,
398
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
399
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
400
0
     "%s: invalid data size value exceeds maximum.",
401
0
     function );
402
403
0
    goto on_error;
404
0
  }
405
2.04k
  data_size -= sizeof( creg_key_navigation_header_t );
406
407
/* TODO clone function ? */
408
2.04k
  if( libfdata_area_initialize(
409
2.04k
       &( key_navigation->key_hierarchy_area ),
410
2.04k
       (size64_t) sizeof( creg_key_hierarchy_entry_t ),
411
2.04k
       NULL,
412
2.04k
       NULL,
413
2.04k
       NULL,
414
2.04k
       (int (*)(intptr_t *, intptr_t *, libfdata_area_t *, libfdata_cache_t *, off64_t, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libcreg_io_handle_read_key_hierarchy_entry,
415
2.04k
       NULL,
416
2.04k
       LIBFDATA_DATA_HANDLE_FLAG_NON_MANAGED,
417
2.04k
       error ) != 1 )
418
0
  {
419
0
    libcerror_error_set(
420
0
     error,
421
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
422
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
423
0
     "%s: unable to create key hierarchy area.",
424
0
     function );
425
426
0
    goto on_error;
427
0
  }
428
2.04k
  if( libfdata_area_append_segment(
429
2.04k
       key_navigation->key_hierarchy_area,
430
2.04k
       &entry_index,
431
2.04k
       0,
432
2.04k
       (off64_t) key_hierarchy_entries_data_offset,
433
2.04k
       (size64_t) data_size,
434
2.04k
       0,
435
2.04k
       error ) != 1 )
436
0
  {
437
0
    libcerror_error_set(
438
0
     error,
439
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
440
0
     LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
441
0
     "%s: unable to append segment to key hierarchy area.",
442
0
     function );
443
444
0
    goto on_error;
445
0
  }
446
2.04k
  if( libfcache_cache_initialize(
447
2.04k
       &( key_navigation->key_hierarchy_cache ),
448
2.04k
       LIBCREG_MAXIMUM_CACHE_ENTRIES_KEYS,
449
2.04k
       error ) != 1 )
450
0
  {
451
0
    libcerror_error_set(
452
0
     error,
453
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
454
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
455
0
     "%s: unable to create key hierarchy cache.",
456
0
     function );
457
458
0
    goto on_error;
459
0
  }
460
2.04k
  return( 1 );
461
462
45
on_error:
463
45
  if( key_navigation->key_hierarchy_cache != NULL )
464
0
  {
465
0
    libfcache_cache_free(
466
0
     &( key_navigation->key_hierarchy_cache ),
467
0
     NULL );
468
0
  }
469
45
  if( key_navigation->key_hierarchy_area != NULL )
470
0
  {
471
0
    libfdata_area_free(
472
0
     &( key_navigation->key_hierarchy_area ),
473
0
     NULL );
474
0
  }
475
45
  return( -1 );
476
2.04k
}
477
478
/* Reads the data block
479
 * Returns 1 if successful, 0 if no data block signature was found or -1 on error
480
 */
481
int libcreg_key_navigation_read_data_blocks(
482
     libcreg_key_navigation_t *key_navigation,
483
     libbfio_handle_t *file_io_handle,
484
     off64_t file_offset,
485
     size64_t file_size,
486
     libcerror_error_t **error )
487
2.58k
{
488
2.58k
  libcreg_data_block_t *data_block = NULL;
489
2.58k
  static char *function            = "libcreg_key_navigation_read_data_blocks";
490
2.58k
  int data_block_index             = 0;
491
2.58k
  int result                       = 0;
492
493
2.58k
  if( key_navigation == NULL )
494
0
  {
495
0
    libcerror_error_set(
496
0
     error,
497
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
498
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
499
0
     "%s: invalid key navigation.",
500
0
     function );
501
502
0
    return( -1 );
503
0
  }
504
2.58k
  if( key_navigation->data_blocks_list != NULL )
505
0
  {
506
0
    libcerror_error_set(
507
0
     error,
508
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
509
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
510
0
     "%s: invalid key navigation - data blocks list already set.",
511
0
     function );
512
513
0
    return( -1 );
514
0
  }
515
2.58k
  if( key_navigation->data_blocks_cache != NULL )
516
0
  {
517
0
    libcerror_error_set(
518
0
     error,
519
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
520
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
521
0
     "%s: invalid key navigation - data blocks list already set.",
522
0
     function );
523
524
0
    return( -1 );
525
0
  }
526
2.58k
  if( key_navigation->io_handle == NULL )
527
0
  {
528
0
    libcerror_error_set(
529
0
     error,
530
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
531
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
532
0
     "%s: invalid key navigation - missing IO handle.",
533
0
     function );
534
535
0
    return( -1 );
536
0
  }
537
2.58k
  if( file_offset < 0 )
538
0
  {
539
0
    libcerror_error_set(
540
0
     error,
541
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
542
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_LESS_THAN_ZERO,
543
0
     "%s: invalid file offset value less than zero.",
544
0
     function );
545
546
0
    return( -1 );
547
0
  }
548
2.58k
  if( libfdata_list_initialize(
549
2.58k
       &( key_navigation->data_blocks_list ),
550
2.58k
       (intptr_t *) key_navigation->io_handle,
551
2.58k
       NULL,
552
2.58k
       NULL,
553
2.58k
       (int (*)(intptr_t *, intptr_t *, libfdata_list_element_t *, libfdata_cache_t *, int, off64_t, size64_t, uint32_t, uint8_t, libcerror_error_t **)) &libcreg_key_navigation_read_data_block_element_data,
554
2.58k
       NULL,
555
2.58k
       0,
556
2.58k
       error ) != 1 )
557
0
  {
558
0
    libcerror_error_set(
559
0
     error,
560
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
561
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
562
0
     "%s: unable to create data blocks list.",
563
0
     function );
564
565
0
    goto on_error;
566
0
  }
567
2.67M
  while( (size64_t) file_offset < file_size )
568
2.67M
  {
569
2.67M
    if( libcreg_data_block_initialize(
570
2.67M
         &data_block,
571
2.67M
         error ) != 1 )
572
0
    {
573
0
      libcerror_error_set(
574
0
       error,
575
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
576
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
577
0
       "%s: unable to create data block.",
578
0
       function );
579
580
0
      goto on_error;
581
0
    }
582
#if defined( HAVE_DEBUG_OUTPUT )
583
    if( libcnotify_verbose != 0 )
584
    {
585
      libcnotify_printf(
586
       "%s: reading data block: %d at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
587
       function,
588
       data_block_index,
589
       file_offset,
590
       file_offset );
591
    }
592
#endif
593
2.67M
    result = libcreg_data_block_read_header(
594
2.67M
              data_block,
595
2.67M
              file_io_handle,
596
2.67M
              file_offset,
597
2.67M
              error );
598
599
2.67M
    if( result == -1 )
600
241
    {
601
241
      libcerror_error_set(
602
241
       error,
603
241
       LIBCERROR_ERROR_DOMAIN_IO,
604
241
       LIBCERROR_IO_ERROR_READ_FAILED,
605
241
       "%s: unable to read data block header.",
606
241
       function );
607
608
241
      goto on_error;
609
241
    }
610
2.67M
    else if( result == 0 )
611
226
    {
612
/* TODO mark file as corrupted */
613
226
      if( data_block_index != 0 )
614
71
      {
615
71
        libcerror_error_set(
616
71
         error,
617
71
         LIBCERROR_ERROR_DOMAIN_IO,
618
71
         LIBCERROR_IO_ERROR_READ_FAILED,
619
71
         "%s: missing data block at offset: %" PRIi64 ".",
620
71
         function,
621
71
         file_offset );
622
623
71
        goto on_error;
624
71
      }
625
226
    }
626
2.67M
    else
627
2.67M
    {
628
2.67M
      if( data_block->size == 0 )
629
3
      {
630
3
        libcerror_error_set(
631
3
         error,
632
3
         LIBCERROR_ERROR_DOMAIN_IO,
633
3
         LIBCERROR_IO_ERROR_READ_FAILED,
634
3
         "%s: invalid data block: %d size.",
635
3
         function,
636
3
         data_block_index );
637
638
3
        goto on_error;
639
3
      }
640
2.67M
      if( libfdata_list_append_element(
641
2.67M
           key_navigation->data_blocks_list,
642
2.67M
           &data_block_index,
643
2.67M
           0,
644
2.67M
           (off64_t) data_block->offset,
645
2.67M
           (size64_t) data_block->size,
646
2.67M
           0,
647
2.67M
           error ) != 1 )
648
0
      {
649
0
        libcerror_error_set(
650
0
         error,
651
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
652
0
         LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
653
0
         "%s: unable to append data block: %d to data list.",
654
0
         function,
655
0
         data_block_index );
656
657
0
        goto on_error;
658
0
      }
659
2.67M
      file_offset += data_block->size;
660
2.67M
    }
661
2.67M
    if( libcreg_data_block_free(
662
2.67M
         &data_block,
663
2.67M
         error ) != 1 )
664
0
    {
665
0
      libcerror_error_set(
666
0
       error,
667
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
668
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
669
0
       "%s: unable to free data block.",
670
0
       function );
671
672
0
      goto on_error;
673
0
    }
674
2.67M
    if( result == 0 )
675
155
    {
676
155
      break;
677
155
    }
678
2.67M
    data_block_index++;
679
2.67M
  }
680
2.26k
  if( libfcache_cache_initialize(
681
2.26k
       &( key_navigation->data_blocks_cache ),
682
2.26k
       LIBCREG_MAXIMUM_CACHE_ENTRIES_DATA_BLOCKS,
683
2.26k
       error ) != 1 )
684
0
  {
685
0
    libcerror_error_set(
686
0
     error,
687
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
688
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
689
0
     "%s: unable to create data blocks cache.",
690
0
     function );
691
692
0
    goto on_error;
693
0
  }
694
2.26k
  if( ( data_block_index == 0 )
695
2.26k
   && ( result == 0 ) )
696
1.06k
  {
697
1.06k
    return( 0 );
698
1.06k
  }
699
1.20k
  return( 1 );
700
701
315
on_error:
702
315
  if( data_block != NULL )
703
315
  {
704
315
    libcreg_data_block_free(
705
315
     &data_block,
706
315
     NULL );
707
315
  }
708
315
  if( key_navigation->data_blocks_list != NULL )
709
315
  {
710
315
    libfdata_list_free(
711
315
     &( key_navigation->data_blocks_list ),
712
315
     NULL );
713
315
  }
714
315
  return( -1 );
715
2.26k
}
716
717
/* Retrieves the key hierarchy entry at a specific offset
718
 * Returns 1 if successful or -1 on error
719
 */
720
int libcreg_key_navigation_get_key_hierarchy_entry_at_offset(
721
     libcreg_key_navigation_t *key_navigation,
722
     libbfio_handle_t *file_io_handle,
723
     off64_t key_hierarchy_entry_offset,
724
     libcreg_key_hierarchy_entry_t **key_hierarchy_entry,
725
     libcerror_error_t **error )
726
22.5k
{
727
22.5k
  static char *function = "libcreg_key_navigation_get_key_hierarchy_entry_at_offset";
728
729
22.5k
  if( key_navigation == NULL )
730
0
  {
731
0
    libcerror_error_set(
732
0
     error,
733
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
734
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
735
0
     "%s: invalid key navigation.",
736
0
     function );
737
738
0
    return( -1 );
739
0
  }
740
22.5k
  if( libfdata_area_get_element_value_at_offset(
741
22.5k
       key_navigation->key_hierarchy_area,
742
22.5k
       (intptr_t *) file_io_handle,
743
22.5k
       (libfdata_cache_t *) key_navigation->key_hierarchy_cache,
744
22.5k
       key_hierarchy_entry_offset,
745
22.5k
       (intptr_t **) key_hierarchy_entry,
746
22.5k
       0,
747
22.5k
       error ) != 1 )
748
596
  {
749
596
    libcerror_error_set(
750
596
     error,
751
596
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
752
596
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
753
596
     "%s: unable to retrieve key hierarchy entry at offset: 0x%08" PRIx64 ".",
754
596
     function,
755
596
     key_hierarchy_entry_offset );
756
757
596
    return( -1 );
758
596
  }
759
21.9k
  return( 1 );
760
22.5k
}
761
762
/* Retrieves the number of data blocks
763
 * Returns 1 if successful or -1 on error
764
 */
765
int libcreg_key_navigation_get_number_of_data_blocks(
766
     libcreg_key_navigation_t *key_navigation,
767
     int *number_of_data_blocks,
768
     libcerror_error_t **error )
769
1.20k
{
770
1.20k
  static char *function = "libcreg_key_navigation_get_number_of_data_blocks";
771
772
1.20k
  if( key_navigation == NULL )
773
0
  {
774
0
    libcerror_error_set(
775
0
     error,
776
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
777
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
778
0
     "%s: invalid key navigation.",
779
0
     function );
780
781
0
    return( -1 );
782
0
  }
783
1.20k
  if( libfdata_list_get_number_of_elements(
784
1.20k
       key_navigation->data_blocks_list,
785
1.20k
       number_of_data_blocks,
786
1.20k
       error ) != 1 )
787
0
  {
788
0
    libcerror_error_set(
789
0
     error,
790
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
791
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
792
0
     "%s: unable to retrieve number of data blocks list elements.",
793
0
     function );
794
795
0
    return( -1 );
796
0
  }
797
1.20k
  return( 1 );
798
1.20k
}
799
800
/* Retrieves a specific data block
801
 * Returns 1 if successful or -1 on error
802
 */
803
int libcreg_key_navigation_get_data_block_at_index(
804
     libcreg_key_navigation_t *key_navigation,
805
     libbfio_handle_t *file_io_handle,
806
     int data_block_index,
807
     libcreg_data_block_t **data_block,
808
     libcerror_error_t **error )
809
1.04k
{
810
1.04k
  static char *function = "libcreg_key_navigation_get_data_block_at_index";
811
812
1.04k
  if( key_navigation == NULL )
813
0
  {
814
0
    libcerror_error_set(
815
0
     error,
816
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
817
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
818
0
     "%s: invalid key navigation.",
819
0
     function );
820
821
0
    return( -1 );
822
0
  }
823
1.04k
  if( libfdata_list_get_element_value_by_index(
824
1.04k
       key_navigation->data_blocks_list,
825
1.04k
       (intptr_t *) file_io_handle,
826
1.04k
       (libfdata_cache_t *) key_navigation->data_blocks_cache,
827
1.04k
       data_block_index,
828
1.04k
       (intptr_t **) data_block,
829
1.04k
       0,
830
1.04k
       error ) != 1 )
831
907
  {
832
907
    libcerror_error_set(
833
907
     error,
834
907
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
835
907
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
836
907
     "%s: unable to retrieve data block: %d.",
837
907
     function,
838
907
     data_block_index );
839
840
907
    return( -1 );
841
907
  }
842
139
  return( 1 );
843
1.04k
}
844
845
/* Reads a data block
846
 * Callback function for the data blocks list
847
 * Returns 1 if successful or -1 on error
848
 */
849
int libcreg_key_navigation_read_data_block_element_data(
850
     libcreg_io_handle_t *io_handle,
851
     libbfio_handle_t *file_io_handle,
852
     libfdata_list_element_t *list_element,
853
     libfdata_cache_t *cache,
854
     int data_range_file_index LIBCREG_ATTRIBUTE_UNUSED,
855
     off64_t data_range_offset,
856
     size64_t data_range_size,
857
     uint32_t data_range_flags LIBCREG_ATTRIBUTE_UNUSED,
858
     uint8_t read_flags LIBCREG_ATTRIBUTE_UNUSED,
859
     libcerror_error_t **error )
860
973
{
861
973
  libcreg_data_block_t *data_block = NULL;
862
973
  static char *function            = "libcreg_key_navigation_read_data_block_element_data";
863
864
973
  LIBCREG_UNREFERENCED_PARAMETER( data_range_file_index )
865
973
  LIBCREG_UNREFERENCED_PARAMETER( data_range_flags )
866
973
  LIBCREG_UNREFERENCED_PARAMETER( read_flags )
867
868
973
  if( io_handle == NULL )
869
0
  {
870
0
    libcerror_error_set(
871
0
     error,
872
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
873
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
874
0
     "%s: invalid IO handle.",
875
0
     function );
876
877
0
    return( -1 );
878
0
  }
879
973
  if( libcreg_data_block_initialize(
880
973
       &data_block,
881
973
       error ) != 1 )
882
0
  {
883
0
    libcerror_error_set(
884
0
     error,
885
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
886
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
887
0
     "%s: unable to create data block.",
888
0
     function );
889
890
0
    goto on_error;
891
0
  }
892
#if defined( HAVE_DEBUG_OUTPUT )
893
  if( libcnotify_verbose != 0 )
894
  {
895
    libcnotify_printf(
896
     "%s: reading data block at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
897
     function,
898
     data_range_offset,
899
     data_range_offset );
900
  }
901
#endif
902
973
  if( libcreg_data_block_read_header(
903
973
       data_block,
904
973
       file_io_handle,
905
973
       data_range_offset,
906
973
       error ) != 1 )
907
0
  {
908
0
    libcerror_error_set(
909
0
     error,
910
0
     LIBCERROR_ERROR_DOMAIN_IO,
911
0
     LIBCERROR_IO_ERROR_READ_FAILED,
912
0
     "%s: unable to read data block header.",
913
0
     function );
914
915
0
    goto on_error;
916
0
  }
917
973
  if( (size64_t) data_block->size != data_range_size )
918
0
  {
919
0
    libcerror_error_set(
920
0
     error,
921
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
922
0
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
923
0
     "%s: mismatch in data block size (stored: %" PRIu32 " != calculated: %" PRIu64 ").",
924
0
     function,
925
0
     data_block->size,
926
0
     data_range_size );
927
928
0
    goto on_error;
929
0
  }
930
973
  if( libcreg_data_block_read_entries(
931
973
       data_block,
932
973
       file_io_handle,
933
973
       io_handle->ascii_codepage,
934
973
       error ) != 1 )
935
852
  {
936
852
    libcerror_error_set(
937
852
     error,
938
852
     LIBCERROR_ERROR_DOMAIN_IO,
939
852
     LIBCERROR_IO_ERROR_READ_FAILED,
940
852
     "%s: unable to read key name entries.",
941
852
     function );
942
943
852
    goto on_error;
944
852
  }
945
121
  if( libfdata_list_element_set_element_value(
946
121
       list_element,
947
121
       (intptr_t *) file_io_handle,
948
121
       cache,
949
121
       (intptr_t *) data_block,
950
121
       (int (*)(intptr_t **, libcerror_error_t **)) &libcreg_data_block_free,
951
121
       LIBFDATA_LIST_ELEMENT_VALUE_FLAG_MANAGED,
952
121
       error ) != 1 )
953
0
  {
954
0
    libcerror_error_set(
955
0
     error,
956
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
957
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
958
0
     "%s: unable to set data block as list element value.",
959
0
     function );
960
961
0
    goto on_error;
962
0
  }
963
121
  return( 1 );
964
965
852
on_error:
966
852
  if( data_block != NULL )
967
852
  {
968
852
    libcreg_data_block_free(
969
852
     &data_block,
970
852
     NULL );
971
852
  }
972
852
  return( -1 );
973
121
}
974
975