Coverage Report

Created: 2026-04-10 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfwps/libfwps/libfwps_set.c
Line
Count
Source
1
/*
2
 * Windows Serialized Property Sheet functions
3
 *
4
 * Copyright (C) 2013-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 <system_string.h>
26
#include <types.h>
27
28
#include "libfwps_definitions.h"
29
#include "libfwps_libcerror.h"
30
#include "libfwps_libcnotify.h"
31
#include "libfwps_record.h"
32
#include "libfwps_libfguid.h"
33
#include "libfwps_set.h"
34
#include "libfwps_types.h"
35
36
const char *libfwps_serialized_property_set_signature = "1SPS";
37
38
uint8_t libfwps_format_class_identifier_named_properties[ 16 ] = {
39
  0x05, 0xd5, 0xcd, 0xd5, 0x9c, 0x2e, 0x1b, 0x10, 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae };
40
41
uint8_t libfwps_format_class_identifier_unknown1[ 16 ] = {
42
  0x30, 0xf1, 0x25, 0xb7, 0xef, 0x47, 0x1a, 0x10, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac };
43
44
/* Creates a set
45
 * Make sure the value set is referencing, is set to NULL
46
 * Returns 1 if successful or -1 on error
47
 */
48
int libfwps_set_initialize(
49
     libfwps_set_t **set,
50
     libcerror_error_t **error )
51
206k
{
52
206k
  libfwps_internal_set_t *internal_set = NULL;
53
206k
  static char *function                = "libfwps_set_initialize";
54
55
206k
  if( set == 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 set.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
206k
  if( *set != 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 set value already set.",
73
0
     function );
74
75
0
    return( -1 );
76
0
  }
77
206k
  internal_set = memory_allocate_structure(
78
206k
                  libfwps_internal_set_t );
79
80
206k
  if( internal_set == 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 set.",
87
0
     function );
88
89
0
    goto on_error;
90
0
  }
91
206k
  if( memory_set(
92
206k
       internal_set,
93
206k
       0,
94
206k
       sizeof( libfwps_internal_set_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 set.",
101
0
     function );
102
103
0
    memory_free(
104
0
     internal_set );
105
106
0
    return( -1 );
107
0
  }
108
206k
  if( libcdata_array_initialize(
109
206k
       &( internal_set->records_array ),
110
206k
       0,
111
206k
       error ) != 1 )
112
0
  {
113
0
    libcerror_error_set(
114
0
     error,
115
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
116
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
117
0
     "%s: unable to create records array.",
118
0
     function );
119
120
0
    goto on_error;
121
0
  }
122
206k
  *set = (libfwps_set_t *) internal_set;
123
124
206k
  return( 1 );
125
126
0
on_error:
127
0
  if( internal_set != NULL )
128
0
  {
129
0
    memory_free(
130
0
     internal_set );
131
0
  }
132
0
  return( -1 );
133
206k
}
134
135
/* Frees a set
136
 * Returns 1 if successful or -1 on error
137
 */
138
int libfwps_set_free(
139
     libfwps_set_t **set,
140
     libcerror_error_t **error )
141
2.57k
{
142
2.57k
  libfwps_internal_set_t *internal_set = NULL;
143
2.57k
  static char *function                = "libfwps_set_free";
144
2.57k
  int result                           = 1;
145
146
2.57k
  if( set == NULL )
147
0
  {
148
0
    libcerror_error_set(
149
0
     error,
150
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
151
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
152
0
     "%s: invalid set.",
153
0
     function );
154
155
0
    return( -1 );
156
0
  }
157
2.57k
  if( *set != NULL )
158
2.57k
  {
159
2.57k
    internal_set = (libfwps_internal_set_t *) *set;
160
161
2.57k
    if( internal_set->is_managed == 0 )
162
2.57k
    {
163
2.57k
      if( libfwps_internal_set_free(
164
2.57k
           &internal_set,
165
2.57k
           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 set.",
172
0
         function );
173
174
0
        result = -1;
175
0
      }
176
2.57k
    }
177
2.57k
    *set = NULL;
178
2.57k
  }
179
2.57k
  return( result );
180
2.57k
}
181
182
/* Frees a set
183
 * Returns 1 if successful or -1 on error
184
 */
185
int libfwps_internal_set_free(
186
     libfwps_internal_set_t **internal_set,
187
     libcerror_error_t **error )
188
206k
{
189
206k
  static char *function = "libfwps_internal_set_free";
190
206k
  int result            = 1;
191
192
206k
  if( internal_set == NULL )
193
0
  {
194
0
    libcerror_error_set(
195
0
     error,
196
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
197
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
198
0
     "%s: invalid set.",
199
0
     function );
200
201
0
    return( -1 );
202
0
  }
203
206k
  if( *internal_set != NULL )
204
206k
  {
205
206k
    if( libcdata_array_free(
206
206k
         &( ( *internal_set )->records_array ),
207
206k
         (int(*)(intptr_t **, libcerror_error_t **)) &libfwps_internal_record_free,
208
206k
         error ) != 1 )
209
0
    {
210
0
      libcerror_error_set(
211
0
       error,
212
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
213
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
214
0
       "%s: unable to free records array.",
215
0
       function );
216
217
0
      result = -1;
218
0
    }
219
206k
    memory_free(
220
206k
     *internal_set );
221
222
206k
    *internal_set = NULL;
223
206k
  }
224
206k
  return( result );
225
206k
}
226
227
/* Copies a serialized property set from a byte stream
228
 * Returns 1 if successful or -1 on error
229
 */
230
int libfwps_set_copy_from_byte_stream(
231
     libfwps_set_t *set,
232
     const uint8_t *byte_stream,
233
     size_t byte_stream_size,
234
     int ascii_codepage,
235
     libcerror_error_t **error )
236
206k
{
237
206k
  libfwps_internal_set_t *internal_set = NULL;
238
206k
  libfwps_record_t *property_record    = NULL;
239
206k
  static char *function                = "libfwps_set_copy_from_byte_stream";
240
206k
  size_t byte_stream_offset            = 0;
241
206k
  uint32_t record_data_size            = 0;
242
206k
  uint8_t property_record_type         = 0;
243
206k
  int entry_index                      = 0;
244
206k
  int record_index                     = 0;
245
246
#if defined( HAVE_DEBUG_OUTPUT )
247
        system_character_t guid_string[ 48 ];
248
249
        libfguid_identifier_t *guid          = NULL;
250
  int result                           = 0;
251
#endif
252
253
206k
  if( set == NULL )
254
0
  {
255
0
    libcerror_error_set(
256
0
     error,
257
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
258
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
259
0
     "%s: invalid set.",
260
0
     function );
261
262
0
    return( -1 );
263
0
  }
264
206k
  internal_set = (libfwps_internal_set_t *) set;
265
266
206k
  if( byte_stream == NULL )
267
0
  {
268
0
    libcerror_error_set(
269
0
     error,
270
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
271
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
272
0
     "%s: invalid byte stream.",
273
0
     function );
274
275
0
    return( -1 );
276
0
  }
277
206k
  if( ( byte_stream_size < 24 )
278
206k
   || ( byte_stream_size > (size_t) SSIZE_MAX ) )
279
65
  {
280
65
    libcerror_error_set(
281
65
     error,
282
65
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
283
65
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
284
65
     "%s: invalid byte stream size value out of bounds.",
285
65
     function );
286
287
65
    return( -1 );
288
65
  }
289
#if defined( HAVE_DEBUG_OUTPUT )
290
  if( libcnotify_verbose != 0 )
291
  {
292
    libcnotify_printf(
293
     "%s: property set data:\n",
294
     function );
295
    libcnotify_print_data(
296
     byte_stream,
297
     24,
298
     0 );
299
  }
300
#endif
301
206k
  if( memory_compare(
302
206k
       &( byte_stream[ byte_stream_offset + 4 ] ),
303
206k
       libfwps_serialized_property_set_signature,
304
206k
       4 ) != 0 )
305
92
  {
306
92
    libcerror_error_set(
307
92
     error,
308
92
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
309
92
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
310
92
     "%s: unsupported signature.",
311
92
     function );
312
313
92
    goto on_error;
314
92
  }
315
206k
  byte_stream_copy_to_uint32_little_endian(
316
206k
   byte_stream,
317
206k
   internal_set->size );
318
319
206k
  if( memory_copy(
320
206k
       internal_set->identifier,
321
206k
       &( byte_stream[ byte_stream_offset + 8 ] ),
322
206k
       16 ) == NULL )
323
0
  {
324
0
    libcerror_error_set(
325
0
     error,
326
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
327
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
328
0
     "%s: unable to copy identifier.",
329
0
     function );
330
331
0
    goto on_error;
332
0
  }
333
#if defined( HAVE_DEBUG_OUTPUT )
334
  if( libcnotify_verbose != 0 )
335
  {
336
    libcnotify_printf(
337
     "%s: size\t\t\t\t\t: %" PRIu16 "\n",
338
     function,
339
     internal_set->size );
340
341
    libcnotify_printf(
342
     "%s: signature\t\t\t\t: %c%c%c%c\n",
343
     function,
344
     byte_stream[ byte_stream_offset + 4 ],
345
     byte_stream[ byte_stream_offset + 5 ],
346
     byte_stream[ byte_stream_offset + 6 ],
347
     byte_stream[ byte_stream_offset + 7 ] );
348
349
    if( libfguid_identifier_initialize(
350
         &guid,
351
         error ) != 1 )
352
    {
353
      libcerror_error_set(
354
       error,
355
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
356
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
357
       "%s: unable to create GUID.",
358
       function );
359
360
      goto on_error;
361
    }
362
    if( libfguid_identifier_copy_from_byte_stream(
363
         guid,
364
         internal_set->identifier,
365
         16,
366
         LIBFGUID_ENDIAN_LITTLE,
367
         error ) != 1 )
368
    {
369
      libcerror_error_set(
370
       error,
371
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
372
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
373
       "%s: unable to copy byte stream to GUID.",
374
       function );
375
376
      goto on_error;
377
    }
378
#if defined( HAVE_WIDE_SYSTEM_CHARACTER )
379
    result = libfguid_identifier_copy_to_utf16_string(
380
        guid,
381
        (uint16_t *) guid_string,
382
        48,
383
        LIBFGUID_STRING_FORMAT_FLAG_USE_UPPER_CASE | LIBFGUID_STRING_FORMAT_FLAG_USE_SURROUNDING_BRACES,
384
        error );
385
#else
386
    result = libfguid_identifier_copy_to_utf8_string(
387
        guid,
388
        (uint8_t *) guid_string,
389
        48,
390
        LIBFGUID_STRING_FORMAT_FLAG_USE_UPPER_CASE | LIBFGUID_STRING_FORMAT_FLAG_USE_SURROUNDING_BRACES,
391
        error );
392
#endif
393
    if( result != 1 )
394
    {
395
      libcerror_error_set(
396
       error,
397
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
398
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
399
       "%s: unable to copy GUID to string.",
400
       function );
401
402
      goto on_error;
403
    }
404
    libcnotify_printf(
405
     "%s: format class identifier\t\t: %" PRIs_SYSTEM "\n",
406
     function,
407
     guid_string );
408
409
    if( libfguid_identifier_free(
410
         &guid,
411
         error ) != 1 )
412
    {
413
      libcerror_error_set(
414
       error,
415
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
416
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
417
       "%s: unable to free GUID.",
418
       function );
419
420
      goto on_error;
421
    }
422
  }
423
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
424
425
206k
  if( ( internal_set->size < 24 )
426
206k
   || ( (size_t) internal_set->size > byte_stream_size ) )
427
89
  {
428
89
    libcerror_error_set(
429
89
     error,
430
89
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
431
89
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
432
89
     "%s: invalid property set size value out of bounds.",
433
89
     function );
434
435
89
    goto on_error;
436
89
  }
437
206k
  byte_stream_offset += 24;
438
439
206k
  if( memory_compare(
440
206k
       internal_set->identifier,
441
206k
       libfwps_format_class_identifier_named_properties,
442
206k
       16 ) == 0 )
443
8.39k
  {
444
8.39k
    property_record_type = LIBFWPS_RECORD_TYPE_NAMED;
445
8.39k
  }
446
198k
  else
447
198k
  {
448
198k
    property_record_type = LIBFWPS_RECORD_TYPE_NUMERIC;
449
198k
  }
450
1.13M
  while( byte_stream_offset < byte_stream_size )
451
936k
  {
452
936k
    if( byte_stream_offset > ( byte_stream_size - 4 ) )
453
100
    {
454
100
      libcerror_error_set(
455
100
       error,
456
100
       LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
457
100
       LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
458
100
       "%s: invalid byte stream size value too small.",
459
100
       function );
460
461
100
      goto on_error;
462
100
    }
463
936k
    byte_stream_copy_to_uint32_little_endian(
464
936k
     &( byte_stream[ byte_stream_offset ] ),
465
936k
     record_data_size );
466
467
#if defined( HAVE_DEBUG_OUTPUT )
468
    if( libcnotify_verbose != 0 )
469
    {
470
      libcnotify_printf(
471
       "%s: record: %d data size\t\t\t: %" PRIu32 "\n",
472
       function,
473
       record_index,
474
       record_data_size );
475
    }
476
#endif
477
936k
    if( record_data_size == 0 )
478
3.75k
    {
479
3.75k
      break;
480
3.75k
    }
481
932k
    if( ( record_data_size > byte_stream_size )
482
932k
     || ( byte_stream_offset > ( byte_stream_size - record_data_size ) ) )
483
400
    {
484
400
      libcerror_error_set(
485
400
       error,
486
400
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
487
400
       LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
488
400
       "%s: invalid record: %d data size value out of bounds.",
489
400
       function,
490
400
       record_index );
491
492
400
      goto on_error;
493
400
    }
494
932k
    if( libfwps_record_initialize(
495
932k
         &property_record,
496
932k
         property_record_type,
497
932k
         error ) != 1 )
498
0
    {
499
0
      libcerror_error_set(
500
0
       error,
501
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
502
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
503
0
       "%s: unable to create property record: %d.",
504
0
       function,
505
0
       record_index );
506
507
0
      goto on_error;
508
0
    }
509
932k
    if( libfwps_record_copy_from_byte_stream(
510
932k
         property_record,
511
932k
         &( byte_stream[ byte_stream_offset ] ),
512
932k
         record_data_size,
513
932k
         ascii_codepage,
514
932k
         error ) != 1 )
515
1.79k
    {
516
1.79k
      libcerror_error_set(
517
1.79k
       error,
518
1.79k
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
519
1.79k
       LIBCERROR_RUNTIME_ERROR_COPY_FAILED,
520
1.79k
       "%s: unable to copy property record: %d from byte stream.",
521
1.79k
       function,
522
1.79k
       record_index );
523
524
1.79k
      goto on_error;
525
1.79k
    }
526
930k
    if( libcdata_array_append_entry(
527
930k
         internal_set->records_array,
528
930k
         &entry_index,
529
930k
         (intptr_t *) property_record,
530
930k
         error ) != 1 )
531
0
    {
532
0
      libcerror_error_set(
533
0
       error,
534
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
535
0
       LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
536
0
       "%s: unable to append record: %d to array.",
537
0
       function,
538
0
       record_index );
539
540
0
      goto on_error;
541
0
    }
542
930k
    property_record = NULL;
543
544
930k
    byte_stream_offset += record_data_size;
545
546
930k
    record_index++;
547
930k
  }
548
/* TODO print trailing data */
549
550
#if defined( HAVE_DEBUG_OUTPUT )
551
  if( libcnotify_verbose != 0 )
552
  {
553
    libcnotify_printf(
554
     "\n" );
555
  }
556
#endif
557
204k
  return( 1 );
558
559
2.48k
on_error:
560
#if defined( HAVE_DEBUG_OUTPUT )
561
  if( guid != NULL )
562
  {
563
    libfguid_identifier_free(
564
     &guid,
565
     NULL );
566
  }
567
#endif
568
2.48k
  if( property_record != NULL )
569
1.79k
  {
570
1.79k
    libfwps_internal_record_free(
571
1.79k
     (libfwps_internal_record_t **) &property_record,
572
1.79k
     NULL );
573
1.79k
  }
574
2.48k
  return( -1 );
575
206k
}
576
577
/* Retrieves the identifier
578
 * The identifier is a little-endian GUID and is 16 bytes of size
579
 * Returns 1 if successful or -1 on error
580
 */
581
int libfwps_set_get_identifier(
582
     libfwps_set_t *set,
583
     uint8_t *guid_data,
584
     size_t guid_data_size,
585
     libcerror_error_t **error )
586
0
{
587
0
  libfwps_internal_set_t *internal_set = NULL;
588
0
  static char *function                = "libfwps_set_get_identifier";
589
590
0
  if( set == NULL )
591
0
  {
592
0
    libcerror_error_set(
593
0
     error,
594
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
595
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
596
0
     "%s: invalid set.",
597
0
     function );
598
599
0
    return( -1 );
600
0
  }
601
0
  internal_set = (libfwps_internal_set_t *) set;
602
603
0
  if( guid_data == NULL )
604
0
  {
605
0
    libcerror_error_set(
606
0
     error,
607
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
608
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
609
0
     "%s: invalid GUID data.",
610
0
     function );
611
612
0
    return( -1 );
613
0
  }
614
0
  if( ( guid_data_size < 16 )
615
0
   || ( guid_data_size > SSIZE_MAX ) )
616
0
  {
617
0
    libcerror_error_set(
618
0
     error,
619
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
620
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
621
0
     "%s: invalid GUID data size value out of bounds.",
622
0
     function );
623
624
0
    return( -1 );
625
0
  }
626
0
  if( memory_copy(
627
0
       guid_data,
628
0
       internal_set->identifier,
629
0
       16 ) == NULL )
630
0
  {
631
0
    libcerror_error_set(
632
0
     error,
633
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
634
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
635
0
     "%s: unable to copy identifier.",
636
0
     function );
637
638
0
    return( -1 );
639
0
  }
640
0
  return( 1 );
641
0
}
642
643
/* Retrieves the number of records
644
 * Returns 1 if successful or -1 on error
645
 */
646
int libfwps_set_get_number_of_records(
647
     libfwps_set_t *set,
648
     int *number_of_records,
649
     libcerror_error_t **error )
650
1.26k
{
651
1.26k
  libfwps_internal_set_t *internal_set = NULL;
652
1.26k
  static char *function                = "libfwps_set_get_number_of_records";
653
654
1.26k
  if( set == NULL )
655
0
  {
656
0
    libcerror_error_set(
657
0
     error,
658
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
659
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
660
0
     "%s: invalid set.",
661
0
     function );
662
663
0
    return( -1 );
664
0
  }
665
1.26k
  internal_set = (libfwps_internal_set_t *) set;
666
667
1.26k
  if( libcdata_array_get_number_of_entries(
668
1.26k
       internal_set->records_array,
669
1.26k
       number_of_records,
670
1.26k
       error ) != 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 number of records.",
677
0
     function );
678
679
0
    return( -1 );
680
0
  }
681
1.26k
  return( 1 );
682
1.26k
}
683
684
/* Retrieves a specific record
685
 * Returns 1 if successful or -1 on error
686
 */
687
int libfwps_set_get_record_by_index(
688
     libfwps_set_t *set,
689
     int record_index,
690
     libfwps_record_t **record,
691
     libcerror_error_t **error )
692
595
{
693
595
  libfwps_internal_set_t *internal_set = NULL;
694
595
  static char *function                = "libfwps_set_get_record_by_index";
695
696
595
  if( set == 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 set.",
703
0
     function );
704
705
0
    return( -1 );
706
0
  }
707
595
  internal_set = (libfwps_internal_set_t *) set;
708
709
595
  if( libcdata_array_get_entry_by_index(
710
595
       internal_set->records_array,
711
595
       record_index,
712
595
       (intptr_t **) record,
713
595
       error ) != 1 )
714
0
  {
715
0
    libcerror_error_set(
716
0
     error,
717
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
718
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
719
0
     "%s: unable to retrieve record: %d.",
720
0
     function,
721
0
     record_index );
722
723
0
    return( -1 );
724
0
  }
725
595
  return( 1 );
726
595
}
727