Coverage Report

Created: 2025-08-28 07:10

/src/libcreg/libcreg/libcreg_key_item.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Key item values 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 <memory.h>
24
#include <types.h>
25
26
#if defined( HAVE_WCTYPE_H ) || defined( HAVE_WINAPI )
27
#include <wctype.h>
28
#endif
29
30
#include "libcreg_data_block.h"
31
#include "libcreg_definitions.h"
32
#include "libcreg_io_handle.h"
33
#include "libcreg_key_descriptor.h"
34
#include "libcreg_key_hierarchy_entry.h"
35
#include "libcreg_key_item.h"
36
#include "libcreg_key_name_entry.h"
37
#include "libcreg_key_navigation.h"
38
#include "libcreg_libbfio.h"
39
#include "libcreg_libcdata.h"
40
#include "libcreg_libcerror.h"
41
#include "libcreg_libcnotify.h"
42
#include "libcreg_libuna.h"
43
#include "libcreg_value_entry.h"
44
45
#include "creg_key_navigation.h"
46
47
/* Creates a key item
48
 * Make sure the value key_item is referencing, is set to NULL
49
 * Returns 1 if successful or -1 on error
50
 */
51
int libcreg_key_item_initialize(
52
     libcreg_key_item_t **key_item,
53
     libcerror_error_t **error )
54
2.47k
{
55
2.47k
  static char *function = "libcreg_key_item_initialize";
56
57
2.47k
  if( key_item == NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
63
0
     "%s: invalid key item.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
2.47k
  if( *key_item != NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
73
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
74
0
     "%s: invalid key item value already set.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
2.47k
  *key_item = memory_allocate_structure(
80
2.47k
               libcreg_key_item_t );
81
82
2.47k
  if( *key_item == NULL )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
87
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
88
0
     "%s: unable to create key item.",
89
0
     function );
90
91
0
    goto on_error;
92
0
  }
93
2.47k
  if( memory_set(
94
2.47k
       *key_item,
95
2.47k
       0,
96
2.47k
       sizeof( libcreg_key_item_t ) ) == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
101
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
102
0
     "%s: unable to clear key item.",
103
0
     function );
104
105
0
    memory_free(
106
0
     *key_item );
107
108
0
    *key_item = NULL;
109
110
0
    return( -1 );
111
0
  }
112
2.47k
  if( libcdata_array_initialize(
113
2.47k
       &( ( *key_item )->sub_key_descriptors_array ),
114
2.47k
       0,
115
2.47k
       error ) != 1 )
116
0
  {
117
0
    libcerror_error_set(
118
0
     error,
119
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
120
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
121
0
     "%s: unable to create sub key descriptors array.",
122
0
     function );
123
124
0
    goto on_error;
125
0
  }
126
2.47k
  if( libcdata_range_list_initialize(
127
2.47k
       &( ( *key_item )->sub_key_range_list ),
128
2.47k
       error ) != 1 )
129
0
  {
130
0
    libcerror_error_set(
131
0
     error,
132
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
133
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
134
0
     "%s: unable to create sub key range list.",
135
0
     function );
136
137
0
    goto on_error;
138
0
  }
139
2.47k
  return( 1 );
140
141
0
on_error:
142
0
  if( *key_item != NULL )
143
0
  {
144
0
    if( ( *key_item )->sub_key_descriptors_array != NULL )
145
0
    {
146
0
      libcdata_array_free(
147
0
       &( ( *key_item )->sub_key_descriptors_array ),
148
0
       NULL,
149
0
       NULL );
150
0
    }
151
0
    memory_free(
152
0
     *key_item );
153
154
0
    *key_item = NULL;
155
0
  }
156
0
  return( -1 );
157
2.47k
}
158
159
/* Frees a key item
160
 * Returns 1 if successful or -1 on error
161
 */
162
int libcreg_key_item_free(
163
     libcreg_key_item_t **key_item,
164
     libcerror_error_t **error )
165
2.47k
{
166
2.47k
  static char *function = "libcreg_key_item_free";
167
2.47k
  int result            = 1;
168
169
2.47k
  if( key_item == NULL )
170
0
  {
171
0
    libcerror_error_set(
172
0
     error,
173
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
174
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
175
0
     "%s: invalid key item.",
176
0
     function );
177
178
0
    return( -1 );
179
0
  }
180
2.47k
  if( *key_item != NULL )
181
2.47k
  {
182
    /* The key_name_entry reference is freed elsewhere */
183
184
2.47k
    if( libcdata_array_free(
185
2.47k
         &( ( *key_item )->sub_key_descriptors_array ),
186
2.47k
         (int (*)(intptr_t **, libcerror_error_t **)) &libcreg_key_descriptor_free,
187
2.47k
         error ) != 1 )
188
0
    {
189
0
      libcerror_error_set(
190
0
       error,
191
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
192
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
193
0
       "%s: unable to free sub key descriptors array.",
194
0
       function );
195
196
0
      result = -1;
197
0
    }
198
2.47k
    if( libcdata_range_list_free(
199
2.47k
         &( ( *key_item )->sub_key_range_list ),
200
2.47k
         NULL,
201
2.47k
         error ) != 1 )
202
0
    {
203
0
      libcerror_error_set(
204
0
       error,
205
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
206
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
207
0
       "%s: unable to free sub key range list.",
208
0
       function );
209
210
0
      result = -1;
211
0
    }
212
2.47k
    memory_free(
213
2.47k
     *key_item );
214
215
2.47k
    *key_item = NULL;
216
2.47k
  }
217
2.47k
  return( result );
218
2.47k
}
219
220
/* Reads a key item
221
 * Returns 1 if successful or -1 on error
222
 */
223
int libcreg_key_item_read(
224
     libcreg_key_item_t *key_item,
225
     libbfio_handle_t *file_io_handle,
226
     libcreg_key_navigation_t *key_navigation,
227
     off64_t key_offset,
228
     libcerror_error_t **error )
229
2.47k
{
230
2.47k
  libcreg_data_block_t *data_block                   = NULL;
231
2.47k
  libcreg_key_descriptor_t *sub_key_descriptor       = NULL;
232
2.47k
  libcreg_key_hierarchy_entry_t *key_hierarchy_entry = NULL;
233
2.47k
  static char *function                              = "libcreg_key_item_read";
234
2.47k
  off64_t sub_key_offset                             = 0;
235
2.47k
  int entry_index                                    = 0;
236
2.47k
  int recursion_depth                                = 0;
237
2.47k
  int result                                         = 0;
238
239
2.47k
  if( key_item == NULL )
240
0
  {
241
0
    libcerror_error_set(
242
0
     error,
243
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
244
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
245
0
     "%s: invalid key item.",
246
0
     function );
247
248
0
    return( -1 );
249
0
  }
250
2.47k
  if( key_item->key_name_entry != NULL )
251
0
  {
252
0
    libcerror_error_set(
253
0
     error,
254
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
255
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
256
0
     "%s: invalid key item - key name entry value already set.",
257
0
     function );
258
259
0
    return( -1 );
260
0
  }
261
2.47k
  if( key_navigation == NULL )
262
3
  {
263
3
    libcerror_error_set(
264
3
     error,
265
3
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
266
3
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
267
3
     "%s: invalid key navigation.",
268
3
     function );
269
270
3
    return( -1 );
271
3
  }
272
2.47k
  if( key_navigation->io_handle == NULL )
273
0
  {
274
0
    libcerror_error_set(
275
0
     error,
276
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
277
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
278
0
     "%s: invalid key navigation - missing IO handle.",
279
0
     function );
280
281
0
    return( -1 );
282
0
  }
283
2.47k
  if( libcreg_key_navigation_get_key_hierarchy_entry_at_offset(
284
2.47k
       key_navigation,
285
2.47k
       file_io_handle,
286
2.47k
       key_offset,
287
2.47k
       &key_hierarchy_entry,
288
2.47k
       error ) != 1 )
289
79
  {
290
79
    libcerror_error_set(
291
79
     error,
292
79
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
293
79
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
294
79
     "%s: unable to retrieve key hierarchy entry for offset: %" PRIi64 ".",
295
79
     function,
296
79
     key_offset );
297
298
79
    goto on_error;
299
79
  }
300
2.39k
  if( key_hierarchy_entry == NULL )
301
0
  {
302
0
    libcerror_error_set(
303
0
     error,
304
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
305
0
     LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
306
0
     "%s: missing key hierarchy entry for offset: %" PRIi64 ".",
307
0
     function,
308
0
     key_offset );
309
310
0
    goto on_error;
311
0
  }
312
2.39k
  if( (int16_t) key_hierarchy_entry->data_block_number >= 0 )
313
1.04k
  {
314
1.04k
    if( libcreg_key_navigation_get_data_block_at_index(
315
1.04k
         key_navigation,
316
1.04k
         file_io_handle,
317
1.04k
         (int) key_hierarchy_entry->data_block_number,
318
1.04k
         &data_block,
319
1.04k
         error ) != 1 )
320
907
    {
321
907
      libcerror_error_set(
322
907
       error,
323
907
       LIBCERROR_ERROR_DOMAIN_IO,
324
907
       LIBCERROR_IO_ERROR_READ_FAILED,
325
907
       "%s: unable to retrieve data block number: %" PRIu16 ".",
326
907
       function,
327
907
       key_hierarchy_entry->data_block_number );
328
329
907
      goto on_error;
330
907
    }
331
#if defined( HAVE_DEBUG_OUTPUT )
332
    if( libcnotify_verbose != 0 )
333
    {
334
      libcnotify_printf(
335
       "%s: offset\t\t\t\t\t: %" PRIzd " (0x%08" PRIzx ")\n",
336
       function,
337
       key_hierarchy_entry->data_offset,
338
       key_hierarchy_entry->data_offset );
339
340
      libcnotify_printf(
341
       "%s: key name entry number\t\t\t: %" PRIi16 "\n",
342
       function,
343
       (int16_t) key_hierarchy_entry->key_name_entry_number );
344
345
      libcnotify_printf(
346
       "%s: data block number\t\t\t: %" PRIi16 "\n",
347
       function,
348
       (int16_t) key_hierarchy_entry->data_block_number );
349
350
      libcnotify_printf(
351
       "\n" );
352
    }
353
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
354
355
139
    if( libcreg_data_block_get_entry_by_identifier(
356
139
         data_block,
357
139
         key_hierarchy_entry->key_name_entry_number,
358
139
         &( key_item->key_name_entry ),
359
139
         key_navigation->io_handle->ascii_codepage,
360
139
         error ) != 1 )
361
89
    {
362
89
      libcerror_error_set(
363
89
       error,
364
89
       LIBCERROR_ERROR_DOMAIN_IO,
365
89
       LIBCERROR_IO_ERROR_READ_FAILED,
366
89
       "%s: unable to retrieve key entry element number: %" PRIu16 ".",
367
89
       function,
368
89
       key_hierarchy_entry->key_name_entry_number );
369
370
89
      goto on_error;
371
89
    }
372
50
    if( key_item->key_name_entry == NULL )
373
0
    {
374
0
      libcerror_error_set(
375
0
       error,
376
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
377
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
378
0
       "%s: missing key name entry: %" PRIu16 ".",
379
0
       function,
380
0
       key_hierarchy_entry->key_name_entry_number );
381
382
0
      goto on_error;
383
0
    }
384
50
  }
385
1.39k
  sub_key_offset = key_hierarchy_entry->sub_key_offset;
386
387
20.8k
  while( ( sub_key_offset != 0 )
388
20.8k
      && ( sub_key_offset != 0xffffffffUL ) )
389
20.1k
  {
390
20.1k
    if( recursion_depth > LIBCREG_MAXIMUM_SUB_KEY_RECURSION_DEPTH )
391
0
    {
392
0
      libcerror_error_set(
393
0
       error,
394
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
395
0
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
396
0
       "%s: invalid recursion depth value out of bounds.",
397
0
       function );
398
399
0
      goto on_error;
400
0
    }
401
20.1k
    if( libcreg_key_navigation_get_key_hierarchy_entry_at_offset(
402
20.1k
         key_navigation,
403
20.1k
         file_io_handle,
404
20.1k
         sub_key_offset,
405
20.1k
         &key_hierarchy_entry,
406
20.1k
         error ) != 1 )
407
517
    {
408
517
      libcerror_error_set(
409
517
       error,
410
517
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
411
517
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
412
517
       "%s: unable to retrieve key hierarchy entry for offset: %" PRIi64 " (0x%08" PRIx64 ").",
413
517
       function,
414
517
       sub_key_offset,
415
517
       sub_key_offset );
416
417
517
      goto on_error;
418
517
    }
419
19.5k
    if( key_hierarchy_entry == NULL )
420
0
    {
421
0
      libcerror_error_set(
422
0
       error,
423
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
424
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
425
0
       "%s: missing key hierarchy entry for offset: %" PRIi64 " (0x%08" PRIx64 ").",
426
0
       function,
427
0
       sub_key_offset,
428
0
       sub_key_offset );
429
430
0
      goto on_error;
431
0
    }
432
19.5k
    if( libcreg_key_descriptor_initialize(
433
19.5k
         &sub_key_descriptor,
434
19.5k
         error ) != 1 )
435
0
    {
436
0
      libcerror_error_set(
437
0
       error,
438
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
439
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
440
0
       "%s: unable to create sub key descriptor.",
441
0
       function );
442
443
0
      goto on_error;
444
0
    }
445
19.5k
    sub_key_descriptor->key_offset = (uint32_t) sub_key_offset;
446
447
19.5k
    if( libcdata_array_append_entry(
448
19.5k
         key_item->sub_key_descriptors_array,
449
19.5k
         &entry_index,
450
19.5k
         (intptr_t *) sub_key_descriptor,
451
19.5k
         error ) != 1 )
452
0
    {
453
0
      libcerror_error_set(
454
0
       error,
455
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
456
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
457
0
       "%s: unable to append sub key descriptor to array.",
458
0
       function );
459
460
0
      goto on_error;
461
0
    }
462
19.5k
    sub_key_descriptor = NULL;
463
464
19.5k
    if( libcdata_range_list_insert_range(
465
19.5k
         key_item->sub_key_range_list,
466
19.5k
         (uint64_t) sub_key_offset,
467
19.5k
         (uint64_t) sizeof( creg_key_hierarchy_entry_t ),
468
19.5k
         NULL,
469
19.5k
         NULL,
470
19.5k
         NULL,
471
19.5k
         error ) == -1 )
472
0
    {
473
0
      libcerror_error_set(
474
0
       error,
475
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
476
0
       LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
477
0
       "%s: unable to insert sub key navigation record range into range list.",
478
0
       function );
479
480
0
      goto on_error;
481
0
    }
482
19.5k
    if( ( key_hierarchy_entry->next_key_offset != 0 )
483
19.5k
     && ( key_hierarchy_entry->next_key_offset != 0xffffffffUL ) )
484
18.8k
    {
485
18.8k
      result = libcdata_range_list_range_has_overlapping_range(
486
18.8k
                key_item->sub_key_range_list,
487
18.8k
                (uint64_t) key_hierarchy_entry->next_key_offset,
488
18.8k
                (uint64_t) sizeof( creg_key_hierarchy_entry_t ),
489
18.8k
                error );
490
491
18.8k
      if( result == -1 )
492
0
      {
493
0
        libcerror_error_set(
494
0
         error,
495
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
496
0
         LIBCERROR_RUNTIME_ERROR_GET_FAILED,
497
0
         "%s: unable to determine if there is an overlapping key navigation record range in the range list.",
498
0
         function );
499
500
0
        goto on_error;
501
0
      }
502
18.8k
      else if( result != 0 )
503
91
      {
504
91
        libcerror_error_set(
505
91
         error,
506
91
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
507
91
         LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
508
91
         "%s: invalid next key navigation record offset: %" PRIu32 " (0x%08" PRIu32 ") value already read.",
509
91
         function,
510
91
         key_hierarchy_entry->next_key_offset,
511
91
         key_hierarchy_entry->next_key_offset );
512
513
91
        goto on_error;
514
91
      }
515
18.8k
    }
516
19.5k
    sub_key_offset = (off64_t) key_hierarchy_entry->next_key_offset;
517
518
19.5k
    recursion_depth++;
519
19.5k
  }
520
787
  return( 1 );
521
522
1.68k
on_error:
523
1.68k
  if( sub_key_descriptor != NULL )
524
0
  {
525
0
    libcreg_key_descriptor_free(
526
0
     &sub_key_descriptor,
527
0
     NULL );
528
0
  }
529
1.68k
  return( -1 );
530
1.39k
}
531
532
/* Determines if the key item is corrupted
533
 * Returns 1 if corrupted, 0 if not or -1 on error
534
 */
535
int libcreg_key_item_is_corrupted(
536
     libcreg_key_item_t *key_item,
537
     libcerror_error_t **error )
538
0
{
539
0
  static char *function = "libcreg_key_item_is_corrupted";
540
541
0
  if( key_item == NULL )
542
0
  {
543
0
    libcerror_error_set(
544
0
     error,
545
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
546
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
547
0
     "%s: invalid key item.",
548
0
     function );
549
550
0
    return( -1 );
551
0
  }
552
0
  if( ( key_item->item_flags & LIBCREG_ITEM_FLAG_IS_CORRUPTED ) != 0 )
553
0
  {
554
0
    return( 1 );
555
0
  }
556
0
  return( 0 );
557
0
}
558
559
/* Retrieves the key name size
560
 * Returns 1 if successful or -1 on error
561
 */
562
int libcreg_key_item_get_name_size(
563
     libcreg_key_item_t *key_item,
564
     size_t *name_size,
565
     libcerror_error_t **error )
566
0
{
567
0
  static char *function = "libcreg_key_item_get_name_size";
568
569
0
  if( key_item == NULL )
570
0
  {
571
0
    libcerror_error_set(
572
0
     error,
573
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
574
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
575
0
     "%s: invalid key item.",
576
0
     function );
577
578
0
    return( -1 );
579
0
  }
580
0
  if( key_item->key_name_entry == NULL )
581
0
  {
582
0
    if( name_size == NULL )
583
0
    {
584
0
      libcerror_error_set(
585
0
       error,
586
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
587
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
588
0
       "%s: invalid name size.",
589
0
       function );
590
591
0
      return( -1 );
592
0
    }
593
0
    *name_size = 0;
594
0
  }
595
0
  else
596
0
  {
597
0
    if( libcreg_key_name_entry_get_name_size(
598
0
         key_item->key_name_entry,
599
0
         name_size,
600
0
         error ) != 1 )
601
0
    {
602
0
      libcerror_error_set(
603
0
       error,
604
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
605
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
606
0
       "%s: unable to retrieve name size.",
607
0
       function );
608
609
0
      return( -1 );
610
0
    }
611
0
  }
612
0
  return( 1 );
613
0
}
614
615
/* Retrieves the key name
616
 * Returns 1 if successful or -1 on error
617
 */
618
int libcreg_key_item_get_name(
619
     libcreg_key_item_t *key_item,
620
     uint8_t *name,
621
     size_t name_size,
622
     libcerror_error_t **error )
623
0
{
624
0
  static char *function = "libcreg_key_item_get_name";
625
626
0
  if( key_item == NULL )
627
0
  {
628
0
    libcerror_error_set(
629
0
     error,
630
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
631
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
632
0
     "%s: invalid key item.",
633
0
     function );
634
635
0
    return( -1 );
636
0
  }
637
0
  if( key_item->key_name_entry == NULL )
638
0
  {
639
0
    if( name == NULL )
640
0
    {
641
0
      libcerror_error_set(
642
0
       error,
643
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
644
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
645
0
       "%s: invalid name.",
646
0
       function );
647
648
0
      return( -1 );
649
0
    }
650
0
    if( name_size < 1 )
651
0
    {
652
0
      libcerror_error_set(
653
0
       error,
654
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
655
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
656
0
       "%s: invalid name size value out of bounds.",
657
0
       function );
658
659
0
      return( -1 );
660
0
    }
661
0
    name[ 0 ] = 0;
662
0
  }
663
0
  else
664
0
  {
665
0
    if( libcreg_key_name_entry_get_name(
666
0
         key_item->key_name_entry,
667
0
         name,
668
0
         name_size,
669
0
         error ) != 1 )
670
0
    {
671
0
      libcerror_error_set(
672
0
       error,
673
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
674
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
675
0
       "%s: unable to retrieve name.",
676
0
       function );
677
678
0
      return( -1 );
679
0
    }
680
0
  }
681
0
  return( 1 );
682
0
}
683
684
/* Retrieves the UTF-8 string size of the key name
685
 * The returned size includes the end of string character
686
 * Returns 1 if successful or -1 on error
687
 */
688
int libcreg_key_item_get_utf8_name_size(
689
     libcreg_key_item_t *key_item,
690
     size_t *utf8_string_size,
691
     int ascii_codepage,
692
     libcerror_error_t **error )
693
0
{
694
0
  static char *function = "libcreg_key_item_get_utf8_name_size";
695
696
0
  if( key_item == NULL )
697
0
  {
698
0
    libcerror_error_set(
699
0
     error,
700
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
701
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
702
0
     "%s: invalid key item.",
703
0
     function );
704
705
0
    return( -1 );
706
0
  }
707
0
  if( key_item->key_name_entry == NULL )
708
0
  {
709
0
    if( utf8_string_size == NULL )
710
0
    {
711
0
      libcerror_error_set(
712
0
       error,
713
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
714
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
715
0
       "%s: invalid UTF-8 string size.",
716
0
       function );
717
718
0
      return( -1 );
719
0
    }
720
0
    *utf8_string_size = 0;
721
0
  }
722
0
  else
723
0
  {
724
0
    if( libcreg_key_name_entry_get_utf8_name_size(
725
0
         key_item->key_name_entry,
726
0
         utf8_string_size,
727
0
         ascii_codepage,
728
0
         error ) != 1 )
729
0
    {
730
0
      libcerror_error_set(
731
0
       error,
732
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
733
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
734
0
       "%s: unable to retrieve UTF-8 name size.",
735
0
       function );
736
737
0
      return( -1 );
738
0
    }
739
0
  }
740
0
  return( 1 );
741
0
}
742
743
/* Retrieves the UTF-8 string value of the key name
744
 * The function uses a codepage if necessary, it uses the codepage set for the library
745
 * The size should include the end of string character
746
 * Returns 1 if successful or -1 on error
747
 */
748
int libcreg_key_item_get_utf8_name(
749
     libcreg_key_item_t *key_item,
750
     uint8_t *utf8_string,
751
     size_t utf8_string_size,
752
     int ascii_codepage,
753
     libcerror_error_t **error )
754
0
{
755
0
  static char *function = "libcreg_key_item_get_utf8_name";
756
757
0
  if( key_item == NULL )
758
0
  {
759
0
    libcerror_error_set(
760
0
     error,
761
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
762
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
763
0
     "%s: invalid key item.",
764
0
     function );
765
766
0
    return( -1 );
767
0
  }
768
0
  if( key_item->key_name_entry == NULL )
769
0
  {
770
0
    if( utf8_string == NULL )
771
0
    {
772
0
      libcerror_error_set(
773
0
       error,
774
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
775
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
776
0
       "%s: invalid UTF-8 string.",
777
0
       function );
778
779
0
      return( -1 );
780
0
    }
781
0
    if( utf8_string_size < 1 )
782
0
    {
783
0
      libcerror_error_set(
784
0
       error,
785
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
786
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
787
0
       "%s: invalid UTF-8 string size value out of bounds.",
788
0
       function );
789
790
0
      return( -1 );
791
0
    }
792
0
    utf8_string[ 0 ] = 0;
793
0
  }
794
0
  else
795
0
  {
796
0
    if( libcreg_key_name_entry_get_utf8_name(
797
0
         key_item->key_name_entry,
798
0
         utf8_string,
799
0
         utf8_string_size,
800
0
         ascii_codepage,
801
0
         error ) != 1 )
802
0
    {
803
0
      libcerror_error_set(
804
0
       error,
805
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
806
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
807
0
       "%s: unable to retrieve UTF-8 name.",
808
0
       function );
809
810
0
      return( -1 );
811
0
    }
812
0
  }
813
0
  return( 1 );
814
0
}
815
816
/* Retrieves the UTF-16 string size of the key name
817
 * The returned size includes the end of string character
818
 * Returns 1 if successful or -1 on error
819
 */
820
int libcreg_key_item_get_utf16_name_size(
821
     libcreg_key_item_t *key_item,
822
     size_t *utf16_string_size,
823
     int ascii_codepage,
824
     libcerror_error_t **error )
825
0
{
826
0
  static char *function = "libcreg_key_item_get_utf16_name_size";
827
828
0
  if( key_item == NULL )
829
0
  {
830
0
    libcerror_error_set(
831
0
     error,
832
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
833
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
834
0
     "%s: invalid key item.",
835
0
     function );
836
837
0
    return( -1 );
838
0
  }
839
0
  if( key_item->key_name_entry == NULL )
840
0
  {
841
0
    if( utf16_string_size == NULL )
842
0
    {
843
0
      libcerror_error_set(
844
0
       error,
845
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
846
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
847
0
       "%s: invalid UTF-16 string size.",
848
0
       function );
849
850
0
      return( -1 );
851
0
    }
852
0
    *utf16_string_size = 0;
853
0
  }
854
0
  else
855
0
  {
856
0
    if( libcreg_key_name_entry_get_utf16_name_size(
857
0
         key_item->key_name_entry,
858
0
         utf16_string_size,
859
0
         ascii_codepage,
860
0
         error ) != 1 )
861
0
    {
862
0
      libcerror_error_set(
863
0
       error,
864
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
865
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
866
0
       "%s: unable to retrieve UTF-16 name size.",
867
0
       function );
868
869
0
      return( -1 );
870
0
    }
871
0
  }
872
0
  return( 1 );
873
0
}
874
875
/* Retrieves the UTF-16 string value of the key name
876
 * The function uses a codepage if necessary, it uses the codepage set for the library
877
 * The size should include the end of string character
878
 * Returns 1 if successful or -1 on error
879
 */
880
int libcreg_key_item_get_utf16_name(
881
     libcreg_key_item_t *key_item,
882
     uint16_t *utf16_string,
883
     size_t utf16_string_size,
884
     int ascii_codepage,
885
     libcerror_error_t **error )
886
0
{
887
0
  static char *function = "libcreg_key_item_get_utf16_name";
888
889
0
  if( key_item == NULL )
890
0
  {
891
0
    libcerror_error_set(
892
0
     error,
893
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
894
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
895
0
     "%s: invalid key item.",
896
0
     function );
897
898
0
    return( -1 );
899
0
  }
900
0
  if( key_item->key_name_entry == NULL )
901
0
  {
902
0
    if( utf16_string == NULL )
903
0
    {
904
0
      libcerror_error_set(
905
0
       error,
906
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
907
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
908
0
       "%s: invalid UTF-16 string.",
909
0
       function );
910
911
0
      return( -1 );
912
0
    }
913
0
    if( utf16_string_size < 1 )
914
0
    {
915
0
      libcerror_error_set(
916
0
       error,
917
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
918
0
       LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
919
0
       "%s: invalid UTF-16 string size value out of bounds.",
920
0
       function );
921
922
0
      return( -1 );
923
0
    }
924
0
    utf16_string[ 0 ] = 0;
925
0
  }
926
0
  else
927
0
  {
928
0
    if( libcreg_key_name_entry_get_utf16_name(
929
0
         key_item->key_name_entry,
930
0
         utf16_string,
931
0
         utf16_string_size,
932
0
         ascii_codepage,
933
0
         error ) != 1 )
934
0
    {
935
0
      libcerror_error_set(
936
0
       error,
937
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
938
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
939
0
       "%s: unable to retrieve UTF-16 name.",
940
0
       function );
941
942
0
      return( -1 );
943
0
    }
944
0
  }
945
0
  return( 1 );
946
0
}
947
948
/* Retrieves the number of value entries
949
 * Returns 1 if successful or -1 on error
950
 */
951
int libcreg_key_item_get_number_of_value_entries(
952
     libcreg_key_item_t *key_item,
953
     int *number_of_value_entries,
954
     libcerror_error_t **error )
955
148
{
956
148
  static char *function = "libcreg_key_item_get_number_of_value_entries";
957
958
148
  if( key_item == NULL )
959
0
  {
960
0
    libcerror_error_set(
961
0
     error,
962
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
963
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
964
0
     "%s: invalid key item.",
965
0
     function );
966
967
0
    return( -1 );
968
0
  }
969
148
  if( key_item->key_name_entry == NULL )
970
142
  {
971
142
    if( number_of_value_entries == NULL )
972
0
    {
973
0
      libcerror_error_set(
974
0
       error,
975
0
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
976
0
       LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
977
0
       "%s: invalid number of value entries.",
978
0
       function );
979
980
0
      return( -1 );
981
0
    }
982
142
    *number_of_value_entries = 0;
983
142
  }
984
6
  else
985
6
  {
986
6
    if( libcreg_key_name_entry_get_number_of_entries(
987
6
         key_item->key_name_entry,
988
6
         number_of_value_entries,
989
6
         error ) != 1 )
990
0
    {
991
0
      libcerror_error_set(
992
0
       error,
993
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
994
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
995
0
       "%s: unable to retrieve number of entries.",
996
0
       function );
997
998
0
      return( -1 );
999
0
    }
1000
6
  }
1001
148
  return( 1 );
1002
148
}
1003
1004
/* Retrieves a specific value entry
1005
 * Returns 1 if successful or -1 on error
1006
 */
1007
int libcreg_key_item_get_value_entry_by_index(
1008
     libcreg_key_item_t *key_item,
1009
     int value_index,
1010
     libcreg_value_entry_t **value_entry,
1011
     libcerror_error_t **error )
1012
148
{
1013
148
  static char *function = "libcreg_key_item_get_value_entry_by_index";
1014
1015
148
  if( key_item == NULL )
1016
0
  {
1017
0
    libcerror_error_set(
1018
0
     error,
1019
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1020
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1021
0
     "%s: invalid key item.",
1022
0
     function );
1023
1024
0
    return( -1 );
1025
0
  }
1026
148
  if( libcreg_key_name_entry_get_entry_by_index(
1027
148
       key_item->key_name_entry,
1028
148
       value_index,
1029
148
       value_entry,
1030
148
       error ) != 1 )
1031
144
  {
1032
144
    libcerror_error_set(
1033
144
     error,
1034
144
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1035
144
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1036
144
     "%s: unable to retrieve value entry: %d.",
1037
144
     function,
1038
144
     value_index );
1039
1040
144
    return( -1 );
1041
144
  }
1042
4
  return( 1 );
1043
148
}
1044
1045
/* Retrieves the value entry for the specific UTF-8 encoded name
1046
 * To retrieve the default value specify value name as NULL and its length as 0
1047
 * Returns 1 if successful, 0 if no such value or -1 on error
1048
 */
1049
int libcreg_key_item_get_value_by_utf8_name(
1050
     libcreg_key_item_t *key_item,
1051
     const uint8_t *utf8_string,
1052
     size_t utf8_string_length,
1053
     int ascii_codepage,
1054
     libcreg_value_entry_t **value_entry,
1055
     libcerror_error_t **error )
1056
0
{
1057
0
  libcreg_value_entry_t *safe_value_entry      = NULL;
1058
0
  static char *function                        = "libcreg_key_item_get_value_by_utf8_name";
1059
0
  libuna_unicode_character_t unicode_character = 0;
1060
0
  size_t utf8_string_index                     = 0;
1061
0
  uint32_t name_hash                           = 0;
1062
0
  int number_of_values                         = 0;
1063
0
  int result                                   = 0;
1064
0
  int value_index                              = 0;
1065
1066
0
  if( key_item == NULL )
1067
0
  {
1068
0
    libcerror_error_set(
1069
0
     error,
1070
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1071
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1072
0
     "%s: invalid key item.",
1073
0
     function );
1074
1075
0
    return( -1 );
1076
0
  }
1077
0
  if( ( utf8_string == NULL )
1078
0
   && ( utf8_string_length != 0 ) )
1079
0
  {
1080
0
    libcerror_error_set(
1081
0
     error,
1082
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1083
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1084
0
     "%s: invalid UTF-8 string.",
1085
0
     function );
1086
1087
0
    return( -1 );
1088
0
  }
1089
0
  if( utf8_string_length > (size_t) SSIZE_MAX )
1090
0
  {
1091
0
    libcerror_error_set(
1092
0
     error,
1093
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1094
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1095
0
     "%s: invalid UTF-8 string length value exceeds maximum.",
1096
0
     function );
1097
1098
0
    return( -1 );
1099
0
  }
1100
0
  if( value_entry == NULL )
1101
0
  {
1102
0
    libcerror_error_set(
1103
0
     error,
1104
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1105
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1106
0
     "%s: invalid value entry.",
1107
0
     function );
1108
1109
0
    return( -1 );
1110
0
  }
1111
0
  if( libcreg_key_name_entry_get_number_of_entries(
1112
0
       key_item->key_name_entry,
1113
0
       &number_of_values,
1114
0
       error ) != 1 )
1115
0
  {
1116
0
    libcerror_error_set(
1117
0
     error,
1118
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1119
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1120
0
     "%s: unable to retrieve number of entries.",
1121
0
     function );
1122
1123
0
    return( -1 );
1124
0
  }
1125
0
  if( number_of_values == 0 )
1126
0
  {
1127
0
    return( 0 );
1128
0
  }
1129
0
  while( utf8_string_index < utf8_string_length )
1130
0
  {
1131
0
    if( libuna_unicode_character_copy_from_utf8(
1132
0
         &unicode_character,
1133
0
         utf8_string,
1134
0
         utf8_string_length,
1135
0
         &utf8_string_index,
1136
0
         error ) != 1 )
1137
0
    {
1138
0
      libcerror_error_set(
1139
0
       error,
1140
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1141
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1142
0
       "%s: unable to copy UTF-8 string to Unicode character.",
1143
0
       function );
1144
1145
0
      return( -1 );
1146
0
    }
1147
0
    name_hash *= 37;
1148
0
    name_hash += (uint32_t) towupper( (wint_t) unicode_character );
1149
0
  }
1150
0
  for( value_index = 0;
1151
0
       value_index < number_of_values;
1152
0
       value_index++ )
1153
0
  {
1154
0
    if( libcreg_key_name_entry_get_entry_by_index(
1155
0
         key_item->key_name_entry,
1156
0
         value_index,
1157
0
         &safe_value_entry,
1158
0
         error ) != 1 )
1159
0
    {
1160
0
      libcerror_error_set(
1161
0
       error,
1162
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1163
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1164
0
       "%s: unable to retrieve value entry: %d.",
1165
0
       function,
1166
0
       value_index );
1167
1168
0
      return( -1 );
1169
0
    }
1170
0
    if( safe_value_entry == NULL )
1171
0
    {
1172
0
      libcerror_error_set(
1173
0
       error,
1174
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1175
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1176
0
       "%s: missing value entry: %d.",
1177
0
       function,
1178
0
       value_index );
1179
1180
0
      return( -1 );
1181
0
    }
1182
0
    if( safe_value_entry->name == NULL )
1183
0
    {
1184
0
      if( ( utf8_string == NULL )
1185
0
       && ( utf8_string_length == 0 ) )
1186
0
      {
1187
0
        result = 1;
1188
0
      }
1189
0
    }
1190
0
    else if( utf8_string == NULL )
1191
0
    {
1192
0
      continue;
1193
0
    }
1194
0
    else
1195
0
    {
1196
0
      result = libcreg_value_entry_compare_name_with_utf8_string(
1197
0
          safe_value_entry,
1198
0
          name_hash,
1199
0
          utf8_string,
1200
0
          utf8_string_length,
1201
0
          ascii_codepage,
1202
0
          error );
1203
1204
0
      if( result == -1 )
1205
0
      {
1206
0
        libcerror_error_set(
1207
0
         error,
1208
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1209
0
         LIBCERROR_RUNTIME_ERROR_GENERIC,
1210
0
         "%s: unable to compare value name with UTF-8 string.",
1211
0
         function );
1212
1213
0
        return( -1 );
1214
0
      }
1215
0
    }
1216
0
    if( result != 0 )
1217
0
    {
1218
0
      break;
1219
0
    }
1220
0
  }
1221
0
  if( value_index >= number_of_values )
1222
0
  {
1223
0
    return( 0 );
1224
0
  }
1225
0
  *value_entry = safe_value_entry;
1226
1227
0
  return( 1 );
1228
0
}
1229
1230
/* Retrieves the value entry for the specific UTF-16 encoded name
1231
 * To retrieve the default value specify value name as NULL and its length as 0
1232
 * Returns 1 if successful, 0 if no such value or -1 on error
1233
 */
1234
int libcreg_key_item_get_value_by_utf16_name(
1235
     libcreg_key_item_t *key_item,
1236
     const uint16_t *utf16_string,
1237
     size_t utf16_string_length,
1238
     int ascii_codepage,
1239
     libcreg_value_entry_t **value_entry,
1240
     libcerror_error_t **error )
1241
0
{
1242
0
  libcreg_value_entry_t *safe_value_entry      = NULL;
1243
0
  static char *function                        = "libcreg_key_item_get_value_by_utf16_name";
1244
0
  libuna_unicode_character_t unicode_character = 0;
1245
0
  size_t utf16_string_index                    = 0;
1246
0
  uint32_t name_hash                           = 0;
1247
0
  int number_of_values                         = 0;
1248
0
  int result                                   = 0;
1249
0
  int value_index                              = 0;
1250
1251
0
  if( key_item == NULL )
1252
0
  {
1253
0
    libcerror_error_set(
1254
0
     error,
1255
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1256
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1257
0
     "%s: invalid key item.",
1258
0
     function );
1259
1260
0
    return( -1 );
1261
0
  }
1262
0
  if( ( utf16_string == NULL )
1263
0
   && ( utf16_string_length != 0 ) )
1264
0
  {
1265
0
    libcerror_error_set(
1266
0
     error,
1267
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1268
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1269
0
     "%s: invalid UTF-16 string.",
1270
0
     function );
1271
1272
0
    return( -1 );
1273
0
  }
1274
0
  if( utf16_string_length > (size_t) SSIZE_MAX )
1275
0
  {
1276
0
    libcerror_error_set(
1277
0
     error,
1278
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1279
0
     LIBCERROR_RUNTIME_ERROR_VALUE_EXCEEDS_MAXIMUM,
1280
0
     "%s: invalid UTF-16 string length value exceeds maximum.",
1281
0
     function );
1282
1283
0
    return( -1 );
1284
0
  }
1285
0
  if( value_entry == NULL )
1286
0
  {
1287
0
    libcerror_error_set(
1288
0
     error,
1289
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1290
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1291
0
     "%s: invalid value entry.",
1292
0
     function );
1293
1294
0
    return( -1 );
1295
0
  }
1296
0
  if( libcreg_key_name_entry_get_number_of_entries(
1297
0
       key_item->key_name_entry,
1298
0
       &number_of_values,
1299
0
       error ) != 1 )
1300
0
  {
1301
0
    libcerror_error_set(
1302
0
     error,
1303
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1304
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1305
0
     "%s: unable to retrieve number of entries.",
1306
0
     function );
1307
1308
0
    return( -1 );
1309
0
  }
1310
0
  if( number_of_values == 0 )
1311
0
  {
1312
0
    return( 0 );
1313
0
  }
1314
0
  while( utf16_string_index < utf16_string_length )
1315
0
  {
1316
0
    if( libuna_unicode_character_copy_from_utf16(
1317
0
         &unicode_character,
1318
0
         utf16_string,
1319
0
         utf16_string_length,
1320
0
         &utf16_string_index,
1321
0
         error ) != 1 )
1322
0
    {
1323
0
      libcerror_error_set(
1324
0
       error,
1325
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1326
0
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
1327
0
       "%s: unable to copy UTF-16 string to Unicode character.",
1328
0
       function );
1329
1330
0
      return( -1 );
1331
0
    }
1332
0
    name_hash *= 37;
1333
0
    name_hash += (uint32_t) towupper( (wint_t) unicode_character );
1334
0
  }
1335
0
  for( value_index = 0;
1336
0
       value_index < number_of_values;
1337
0
       value_index++ )
1338
0
  {
1339
0
    if( libcreg_key_name_entry_get_entry_by_index(
1340
0
         key_item->key_name_entry,
1341
0
         value_index,
1342
0
         &safe_value_entry,
1343
0
         error ) != 1 )
1344
0
    {
1345
0
      libcerror_error_set(
1346
0
       error,
1347
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1348
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1349
0
       "%s: unable to retrieve value entry: %d.",
1350
0
       function,
1351
0
       value_index );
1352
1353
0
      return( -1 );
1354
0
    }
1355
0
    if( safe_value_entry == NULL )
1356
0
    {
1357
0
      libcerror_error_set(
1358
0
       error,
1359
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1360
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1361
0
       "%s: missing value entry: %d.",
1362
0
       function,
1363
0
       value_index );
1364
1365
0
      return( -1 );
1366
0
    }
1367
0
    if( safe_value_entry->name == NULL )
1368
0
    {
1369
0
      if( ( utf16_string == NULL )
1370
0
       && ( utf16_string_length == 0 ) )
1371
0
      {
1372
0
        result = 1;
1373
0
      }
1374
0
    }
1375
0
    else if( utf16_string == NULL )
1376
0
    {
1377
0
      continue;
1378
0
    }
1379
0
    else
1380
0
    {
1381
0
      result = libcreg_value_entry_compare_name_with_utf16_string(
1382
0
          safe_value_entry,
1383
0
          name_hash,
1384
0
          utf16_string,
1385
0
          utf16_string_length,
1386
0
          ascii_codepage,
1387
0
          error );
1388
1389
0
      if( result == -1 )
1390
0
      {
1391
0
        libcerror_error_set(
1392
0
         error,
1393
0
         LIBCERROR_ERROR_DOMAIN_RUNTIME,
1394
0
         LIBCERROR_RUNTIME_ERROR_GENERIC,
1395
0
         "%s: unable to compare value name with UTF-8 string.",
1396
0
         function );
1397
1398
0
        return( -1 );
1399
0
      }
1400
0
    }
1401
0
    if( result != 0 )
1402
0
    {
1403
0
      break;
1404
0
    }
1405
0
  }
1406
0
  if( value_index >= number_of_values )
1407
0
  {
1408
0
    return( 0 );
1409
0
  }
1410
0
  *value_entry = safe_value_entry;
1411
1412
0
  return( 1 );
1413
0
}
1414
1415
/* Retrieves the number of sub key descriptors
1416
 * Returns 1 if successful or -1 on error
1417
 */
1418
int libcreg_key_item_get_number_of_sub_key_descriptors(
1419
     libcreg_key_item_t *key_item,
1420
     int *number_of_sub_key_descriptors,
1421
     libcerror_error_t **error )
1422
499
{
1423
499
  static char *function = "libcreg_key_item_get_number_of_sub_key_descriptors";
1424
1425
499
  if( key_item == NULL )
1426
0
  {
1427
0
    libcerror_error_set(
1428
0
     error,
1429
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1430
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1431
0
     "%s: invalid key item.",
1432
0
     function );
1433
1434
0
    return( -1 );
1435
0
  }
1436
499
  if( libcdata_array_get_number_of_entries(
1437
499
       key_item->sub_key_descriptors_array,
1438
499
       number_of_sub_key_descriptors,
1439
499
       error ) != 1 )
1440
0
  {
1441
0
    libcerror_error_set(
1442
0
     error,
1443
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1444
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1445
0
     "%s: unable to retrieve number of sub key descriptors from array.",
1446
0
     function );
1447
1448
0
    return( -1 );
1449
0
  }
1450
499
  return( 1 );
1451
499
}
1452
1453
/* Retrieves a specific sub key descriptor
1454
 * Returns 1 if successful or -1 on error
1455
 */
1456
int libcreg_key_item_get_sub_key_descriptor_by_index(
1457
     libcreg_key_item_t *key_item,
1458
     int sub_key_descriptor_index,
1459
     libcreg_key_descriptor_t **sub_key_descriptor,
1460
     libcerror_error_t **error )
1461
495
{
1462
495
  static char *function = "libcreg_key_item_get_sub_key_descriptor_by_index";
1463
1464
495
  if( key_item == NULL )
1465
0
  {
1466
0
    libcerror_error_set(
1467
0
     error,
1468
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1469
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1470
0
     "%s: invalid key item.",
1471
0
     function );
1472
1473
0
    return( -1 );
1474
0
  }
1475
495
  if( libcdata_array_get_entry_by_index(
1476
495
       key_item->sub_key_descriptors_array,
1477
495
             sub_key_descriptor_index,
1478
495
       (intptr_t **) sub_key_descriptor,
1479
495
       error ) != 1 )
1480
0
  {
1481
0
    libcerror_error_set(
1482
0
     error,
1483
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1484
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1485
0
     "%s: unable to retrieve sub key descriptor: %d from array.",
1486
0
     function,
1487
0
     sub_key_descriptor_index );
1488
1489
0
    return( -1 );
1490
0
  }
1491
495
  return( 1 );
1492
495
}
1493
1494
/* Retrieves the sub key descriptor for the specific UTF-8 encoded name
1495
 * Returns 1 if successful, 0 if no such value or -1 on error
1496
 */
1497
int libcreg_key_item_get_sub_key_descriptor_by_utf8_name(
1498
     libcreg_key_item_t *key_item,
1499
     libbfio_handle_t *file_io_handle,
1500
     libcreg_key_navigation_t *key_navigation,
1501
     const uint8_t *utf8_string,
1502
     size_t utf8_string_length,
1503
     int ascii_codepage,
1504
     libcreg_key_descriptor_t **sub_key_descriptor,
1505
     libcerror_error_t **error )
1506
0
{
1507
0
  libcreg_key_descriptor_t *safe_sub_key_descriptor = NULL;
1508
0
  libcreg_key_item_t *sub_key_item                  = NULL;
1509
0
  static char *function                             = "libcreg_key_item_get_sub_key_descriptor_by_utf8_name";
1510
0
  int number_of_sub_key_descriptors                 = 0;
1511
0
  int result                                        = 0;
1512
0
  int sub_key_descriptor_index                      = 0;
1513
1514
0
  if( key_item == NULL )
1515
0
  {
1516
0
    libcerror_error_set(
1517
0
     error,
1518
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1519
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1520
0
     "%s: invalid key item.",
1521
0
     function );
1522
1523
0
    return( -1 );
1524
0
  }
1525
0
  *sub_key_descriptor = NULL;
1526
1527
/* TODO think of caching and/or optimization
1528
 * e.g. mapping sub key descriptors to name search tree?
1529
 */
1530
0
  if( libcdata_array_get_number_of_entries(
1531
0
       key_item->sub_key_descriptors_array,
1532
0
       &number_of_sub_key_descriptors,
1533
0
       error ) != 1 )
1534
0
  {
1535
0
    libcerror_error_set(
1536
0
     error,
1537
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1538
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1539
0
     "%s: unable to retrieve number of entries from sub key descriptors array.",
1540
0
     function );
1541
1542
0
    goto on_error;
1543
0
  }
1544
0
  for( sub_key_descriptor_index = 0;
1545
0
       sub_key_descriptor_index < number_of_sub_key_descriptors;
1546
0
       sub_key_descriptor_index++ )
1547
0
  {
1548
0
    if( libcdata_array_get_entry_by_index(
1549
0
         key_item->sub_key_descriptors_array,
1550
0
         sub_key_descriptor_index,
1551
0
         (intptr_t **) &safe_sub_key_descriptor,
1552
0
         error ) != 1 )
1553
0
    {
1554
0
      libcerror_error_set(
1555
0
       error,
1556
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1557
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1558
0
       "%s: unable to retrieve sub key descriptor: %d from array.",
1559
0
       function,
1560
0
       sub_key_descriptor_index );
1561
1562
0
      goto on_error;
1563
0
    }
1564
0
    if( safe_sub_key_descriptor == NULL )
1565
0
    {
1566
0
      libcerror_error_set(
1567
0
       error,
1568
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1569
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1570
0
       "%s: missing sub key descriptor: %d.",
1571
0
       function,
1572
0
       sub_key_descriptor_index );
1573
1574
0
      goto on_error;
1575
0
    }
1576
0
    if( libcreg_key_item_initialize(
1577
0
         &sub_key_item,
1578
0
         error ) != 1 )
1579
0
    {
1580
0
      libcerror_error_set(
1581
0
       error,
1582
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1583
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1584
0
       "%s: unable to create sub key item.",
1585
0
       function );
1586
1587
0
      goto on_error;
1588
0
    }
1589
0
    if( libcreg_key_item_read(
1590
0
         sub_key_item,
1591
0
         file_io_handle,
1592
0
         key_navigation,
1593
0
         safe_sub_key_descriptor->key_offset,
1594
0
         error ) != 1 )
1595
0
    {
1596
0
      libcerror_error_set(
1597
0
       error,
1598
0
       LIBCERROR_ERROR_DOMAIN_IO,
1599
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1600
0
       "%s: unable to read sub key item at offset: %" PRIu32 " (0x%08" PRIx32 ").",
1601
0
       function,
1602
0
       safe_sub_key_descriptor->key_offset,
1603
0
       safe_sub_key_descriptor->key_offset );
1604
1605
0
      goto on_error;
1606
0
    }
1607
/* TODO remove or pass name_hash */
1608
0
    result = libcreg_key_name_entry_compare_name_with_utf8_string(
1609
0
              sub_key_item->key_name_entry,
1610
0
              0,
1611
0
              utf8_string,
1612
0
              utf8_string_length,
1613
0
              ascii_codepage,
1614
0
              error );
1615
1616
0
    if( result == -1 )
1617
0
    {
1618
0
      libcerror_error_set(
1619
0
       error,
1620
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1621
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1622
0
       "%s: unable to compare named key with UTF-8 string.",
1623
0
       function );
1624
1625
0
      goto on_error;
1626
0
    }
1627
0
    if( libcreg_key_item_free(
1628
0
         &sub_key_item,
1629
0
         error ) != 1 )
1630
0
    {
1631
0
      libcerror_error_set(
1632
0
       error,
1633
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1634
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1635
0
       "%s: unable to free sub key item.",
1636
0
       function );
1637
1638
0
      goto on_error;
1639
0
    }
1640
0
    if( result != 0 )
1641
0
    {
1642
0
      break;
1643
0
    }
1644
0
  }
1645
0
  if( sub_key_descriptor_index >= number_of_sub_key_descriptors )
1646
0
  {
1647
0
    return( 0 );
1648
0
  }
1649
0
  *sub_key_descriptor = safe_sub_key_descriptor;
1650
1651
0
  return( 1 );
1652
1653
0
on_error:
1654
0
  if( sub_key_item != NULL )
1655
0
  {
1656
0
    libcreg_key_item_free(
1657
0
     &sub_key_item,
1658
0
     NULL );
1659
0
  }
1660
0
  return( -1 );
1661
0
}
1662
1663
/* Retrieves the sub key descriptor for the specific UTF-16 encoded name
1664
 * Returns 1 if successful, 0 if no such value or -1 on error
1665
 */
1666
int libcreg_key_item_get_sub_key_descriptor_by_utf16_name(
1667
     libcreg_key_item_t *key_item,
1668
     libbfio_handle_t *file_io_handle,
1669
     libcreg_key_navigation_t *key_navigation,
1670
     const uint16_t *utf16_string,
1671
     size_t utf16_string_length,
1672
     int ascii_codepage,
1673
     libcreg_key_descriptor_t **sub_key_descriptor,
1674
     libcerror_error_t **error )
1675
0
{
1676
0
  libcreg_key_descriptor_t *safe_sub_key_descriptor = NULL;
1677
0
  libcreg_key_item_t *sub_key_item                  = NULL;
1678
0
  static char *function                             = "libcreg_key_item_get_sub_key_descriptor_by_utf16_name";
1679
0
  int number_of_sub_key_descriptors                 = 0;
1680
0
  int result                                        = 0;
1681
0
  int sub_key_descriptor_index                      = 0;
1682
1683
0
  if( key_item == NULL )
1684
0
  {
1685
0
    libcerror_error_set(
1686
0
     error,
1687
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1688
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1689
0
     "%s: invalid key item.",
1690
0
     function );
1691
1692
0
    return( -1 );
1693
0
  }
1694
0
  *sub_key_descriptor = NULL;
1695
1696
/* TODO think of caching and/or optimization
1697
 * e.g. mapping sub key descriptors to name search tree?
1698
 */
1699
0
  if( libcdata_array_get_number_of_entries(
1700
0
       key_item->sub_key_descriptors_array,
1701
0
       &number_of_sub_key_descriptors,
1702
0
       error ) != 1 )
1703
0
  {
1704
0
    libcerror_error_set(
1705
0
     error,
1706
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
1707
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1708
0
     "%s: unable to retrieve number of entries from sub key descriptors array.",
1709
0
     function );
1710
1711
0
    goto on_error;
1712
0
  }
1713
0
  for( sub_key_descriptor_index = 0;
1714
0
       sub_key_descriptor_index < number_of_sub_key_descriptors;
1715
0
       sub_key_descriptor_index++ )
1716
0
  {
1717
0
    if( libcdata_array_get_entry_by_index(
1718
0
         key_item->sub_key_descriptors_array,
1719
0
         sub_key_descriptor_index,
1720
0
         (intptr_t **) &safe_sub_key_descriptor,
1721
0
         error ) != 1 )
1722
0
    {
1723
0
      libcerror_error_set(
1724
0
       error,
1725
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1726
0
       LIBCERROR_RUNTIME_ERROR_GET_FAILED,
1727
0
       "%s: unable to retrieve sub key descriptor: %d from array.",
1728
0
       function,
1729
0
       sub_key_descriptor_index );
1730
1731
0
      goto on_error;
1732
0
    }
1733
0
    if( safe_sub_key_descriptor == NULL )
1734
0
    {
1735
0
      libcerror_error_set(
1736
0
       error,
1737
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1738
0
       LIBCERROR_RUNTIME_ERROR_VALUE_MISSING,
1739
0
       "%s: missing sub key descriptor: %d.",
1740
0
       function,
1741
0
       sub_key_descriptor_index );
1742
1743
0
      goto on_error;
1744
0
    }
1745
0
    if( libcreg_key_item_initialize(
1746
0
         &sub_key_item,
1747
0
         error ) != 1 )
1748
0
    {
1749
0
      libcerror_error_set(
1750
0
       error,
1751
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1752
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1753
0
       "%s: unable to create sub key item.",
1754
0
       function );
1755
1756
0
      goto on_error;
1757
0
    }
1758
0
    if( libcreg_key_item_read(
1759
0
         sub_key_item,
1760
0
         file_io_handle,
1761
0
         key_navigation,
1762
0
         safe_sub_key_descriptor->key_offset,
1763
0
         error ) != 1 )
1764
0
    {
1765
0
      libcerror_error_set(
1766
0
       error,
1767
0
       LIBCERROR_ERROR_DOMAIN_IO,
1768
0
       LIBCERROR_IO_ERROR_READ_FAILED,
1769
0
       "%s: unable to read sub key item at offset: %" PRIu32 " (0x%08" PRIx32 ").",
1770
0
       function,
1771
0
       safe_sub_key_descriptor->key_offset,
1772
0
       safe_sub_key_descriptor->key_offset );
1773
1774
0
      goto on_error;
1775
0
    }
1776
/* TODO remove or pass name_hash */
1777
0
    result = libcreg_key_name_entry_compare_name_with_utf16_string(
1778
0
              sub_key_item->key_name_entry,
1779
0
              0,
1780
0
              utf16_string,
1781
0
              utf16_string_length,
1782
0
              ascii_codepage,
1783
0
              error );
1784
1785
0
    if( result == -1 )
1786
0
    {
1787
0
      libcerror_error_set(
1788
0
       error,
1789
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1790
0
       LIBCERROR_RUNTIME_ERROR_GENERIC,
1791
0
       "%s: unable to compare named key with UTF-16 string.",
1792
0
       function );
1793
1794
0
      goto on_error;
1795
0
    }
1796
0
    if( libcreg_key_item_free(
1797
0
         &sub_key_item,
1798
0
         error ) != 1 )
1799
0
    {
1800
0
      libcerror_error_set(
1801
0
       error,
1802
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
1803
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1804
0
       "%s: unable to free sub key item.",
1805
0
       function );
1806
1807
0
      goto on_error;
1808
0
    }
1809
0
    if( result != 0 )
1810
0
    {
1811
0
      break;
1812
0
    }
1813
0
  }
1814
0
  if( sub_key_descriptor_index >= number_of_sub_key_descriptors )
1815
0
  {
1816
0
    return( 0 );
1817
0
  }
1818
0
  *sub_key_descriptor = safe_sub_key_descriptor;
1819
1820
0
  return( 1 );
1821
1822
0
on_error:
1823
0
  if( sub_key_item != NULL )
1824
0
  {
1825
0
    libcreg_key_item_free(
1826
0
     &sub_key_item,
1827
0
     NULL );
1828
0
  }
1829
0
  return( -1 );
1830
0
}
1831