Coverage Report

Created: 2025-06-13 07:22

/src/libregf/libregf/libregf_multi_string.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Multi string functions
3
 *
4
 * Copyright (C) 2009-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
#include "libregf_definitions.h"
27
#include "libregf_libcerror.h"
28
#include "libregf_libcnotify.h"
29
#include "libregf_libuna.h"
30
#include "libregf_multi_string.h"
31
#include "libregf_types.h"
32
33
/* Creates multi string
34
 * Make sure the value multi_string is referencing, is set to NULL
35
 * Returns 1 if successful or -1 on error
36
 */
37
int libregf_multi_string_initialize(
38
     libregf_multi_string_t **multi_string,
39
     libcerror_error_t **error )
40
0
{
41
0
  libregf_internal_multi_string_t *internal_multi_string = NULL;
42
0
  static char *function                                  = "libregf_multi_string_initialize";
43
44
0
  if( multi_string == NULL )
45
0
  {
46
0
    libcerror_error_set(
47
0
     error,
48
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
49
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
50
0
     "%s: invalid multi string.",
51
0
     function );
52
53
0
    return( -1 );
54
0
  }
55
0
  if( *multi_string != NULL )
56
0
  {
57
0
    libcerror_error_set(
58
0
     error,
59
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
60
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
61
0
     "%s: invalid multi string value already set.",
62
0
     function );
63
64
0
    return( -1 );
65
0
  }
66
0
  internal_multi_string = memory_allocate_structure(
67
0
                           libregf_internal_multi_string_t );
68
69
0
  if( internal_multi_string == NULL )
70
0
  {
71
0
    libcerror_error_set(
72
0
     error,
73
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
74
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
75
0
     "%s: unable to create multi string.",
76
0
     function );
77
78
0
    goto on_error;
79
0
  }
80
0
  if( memory_set(
81
0
       internal_multi_string,
82
0
       0,
83
0
       sizeof( libregf_internal_multi_string_t ) ) == NULL )
84
0
  {
85
0
    libcerror_error_set(
86
0
     error,
87
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
88
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
89
0
     "%s: unable to clear multi string.",
90
0
     function );
91
92
0
    goto on_error;
93
0
  }
94
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
95
0
  if( libcthreads_read_write_lock_initialize(
96
0
       &( internal_multi_string->read_write_lock ),
97
0
       error ) != 1 )
98
0
  {
99
0
    libcerror_error_set(
100
0
     error,
101
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
102
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
103
0
     "%s: unable to initialize read/write lock.",
104
0
     function );
105
106
0
    goto on_error;
107
0
  }
108
0
#endif
109
0
  *multi_string = (libregf_multi_string_t *) internal_multi_string;
110
111
0
  return( 1 );
112
113
0
on_error:
114
0
  if( internal_multi_string != NULL )
115
0
  {
116
0
    memory_free(
117
0
     internal_multi_string );
118
0
  }
119
0
  return( -1 );
120
0
}
121
122
/* Frees multi string
123
 * Returns 1 if successful or -1 on error
124
 */
125
int libregf_multi_string_free(
126
     libregf_multi_string_t **multi_string,
127
     libcerror_error_t **error )
128
0
{
129
0
  libregf_internal_multi_string_t *internal_multi_string = NULL;
130
0
  static char *function                                  = "libregf_multi_string_free";
131
0
  int result                                             = 1;
132
133
0
  if( multi_string == NULL )
134
0
  {
135
0
    libcerror_error_set(
136
0
     error,
137
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
138
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
139
0
     "%s: invalid multi string.",
140
0
     function );
141
142
0
    return( -1 );
143
0
  }
144
0
  if( *multi_string != NULL )
145
0
  {
146
0
    internal_multi_string = (libregf_internal_multi_string_t *) *multi_string;
147
0
    *multi_string         = NULL;
148
149
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
150
0
    if( libcthreads_read_write_lock_free(
151
0
         &( internal_multi_string->read_write_lock ),
152
0
         error ) != 1 )
153
0
    {
154
0
      libcerror_error_set(
155
0
       error,
156
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
157
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
158
0
       "%s: unable to free read/write lock.",
159
0
       function );
160
161
0
      result = -1;
162
0
    }
163
0
#endif
164
0
    if( internal_multi_string->string_sizes != NULL )
165
0
    {
166
0
      memory_free(
167
0
       internal_multi_string->string_sizes );
168
0
    }
169
0
    if( internal_multi_string->strings != NULL )
170
0
    {
171
0
      memory_free(
172
0
       internal_multi_string->strings );
173
0
    }
174
0
    if( internal_multi_string->data != NULL )
175
0
    {
176
0
      memory_free(
177
0
       internal_multi_string->data );
178
0
    }
179
0
    memory_free(
180
0
     internal_multi_string );
181
0
  }
182
0
  return( result );
183
0
}
184
185
/* Reads the multi string data
186
 * Returns 1 if successful or -1 on error
187
 */
188
int libregf_internal_multi_string_read_data(
189
     libregf_internal_multi_string_t *internal_multi_string,
190
     const uint8_t *data,
191
     size_t data_size,
192
     libcerror_error_t **error )
193
0
{
194
0
  uint8_t *string_start   = NULL;
195
0
  static char *function   = "libregf_multi_string_get_number_of_strings";
196
0
  size_t data_offset      = 0;
197
0
  size_t string_size      = 0;
198
0
  int found_end_of_string = 0;
199
0
  int number_of_strings   = 0;
200
0
  int string_index        = 0;
201
202
0
  if( internal_multi_string == NULL )
203
0
  {
204
0
    libcerror_error_set(
205
0
     error,
206
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
207
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
208
0
     "%s: invalid multi string.",
209
0
     function );
210
211
0
    return( -1 );
212
0
  }
213
0
  if( internal_multi_string->data != NULL )
214
0
  {
215
0
    libcerror_error_set(
216
0
     error,
217
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
218
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
219
0
     "%s: invalid multi string - data already set.",
220
0
     function );
221
222
0
    return( -1 );
223
0
  }
224
0
  if( internal_multi_string->strings != NULL )
225
0
  {
226
0
    libcerror_error_set(
227
0
     error,
228
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
229
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
230
0
     "%s: invalid multi string - strings already set.",
231
0
     function );
232
233
0
    return( -1 );
234
0
  }
235
0
  if( internal_multi_string->string_sizes != NULL )
236
0
  {
237
0
    libcerror_error_set(
238
0
     error,
239
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
240
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
241
0
     "%s: invalid multi string - string sizes already set.",
242
0
     function );
243
244
0
    return( -1 );
245
0
  }
246
0
  if( data == NULL )
247
0
  {
248
0
    libcerror_error_set(
249
0
     error,
250
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
251
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
252
0
     "%s: invalid data.",
253
0
     function );
254
255
0
    return( -1 );
256
0
  }
257
0
  if( ( data_size < 2 )
258
0
   || ( data_size > (size_t) MEMORY_MAXIMUM_ALLOCATION_SIZE ) )
259
0
  {
260
0
    libcerror_error_set(
261
0
     error,
262
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
263
0
     LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
264
0
     "%s: invalid data size value out of bounds.",
265
0
     function );
266
267
0
    return( -1 );
268
0
  }
269
#if defined( HAVE_DEBUG_OUTPUT )
270
  if( libcnotify_verbose != 0 )
271
  {
272
    libcnotify_printf(
273
     "%s: multi string data:\n",
274
     function );
275
    libcnotify_print_data(
276
     data,
277
     data_size,
278
     LIBCNOTIFY_PRINT_DATA_FLAG_GROUP_DATA );
279
  }
280
#endif
281
0
  data_offset = 0;
282
283
0
  while( data_offset < data_size )
284
0
  {
285
0
    found_end_of_string = 0;
286
0
    string_size         = 0;
287
288
0
    while( data_offset <= ( data_size - 2 ) )
289
0
    {
290
0
      string_size += 2;
291
292
0
      if( ( data[ data_offset ] == 0 )
293
0
       && ( data[ data_offset + 1 ] == 0 ) )
294
0
      {
295
0
        data_offset        += 2;
296
0
        found_end_of_string = 1;
297
298
0
        break;
299
0
      }
300
0
      data_offset += 2;
301
0
    }
302
0
    if( found_end_of_string == 0 )
303
0
    {
304
#if defined( HAVE_DEBUG_OUTPUT )
305
      if( libcnotify_verbose != 0 )
306
      {
307
        libcnotify_printf(
308
         "%s: multi string: %d missing end-of-string character.\n",
309
         function,
310
         number_of_strings );
311
      }
312
#endif
313
0
      internal_multi_string->item_flags |= LIBREGF_ITEM_FLAG_IS_CORRUPTED;
314
315
0
      break;
316
0
    }
317
0
    if( string_size == 2 )
318
0
    {
319
0
      break;
320
0
    }
321
0
    number_of_strings++;
322
0
  }
323
0
  if( ( data[ data_offset - 2 ] != 0 )
324
0
   || ( data[ data_offset - 1 ] != 0 ) )
325
0
  {
326
#if defined( HAVE_DEBUG_OUTPUT )
327
    if( libcnotify_verbose != 0 )
328
    {
329
      libcnotify_printf(
330
       "%s: multi string without terminating empty string.\n",
331
       function );
332
    }
333
#endif
334
0
    internal_multi_string->item_flags |= LIBREGF_ITEM_FLAG_IS_CORRUPTED;
335
0
  }
336
0
  internal_multi_string->data = (uint8_t *) memory_allocate(
337
0
                                             sizeof( uint8_t ) * data_size );
338
339
0
  if( internal_multi_string->data == NULL )
340
0
  {
341
0
    libcerror_error_set(
342
0
     error,
343
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
344
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
345
0
     "%s: unable to create data.",
346
0
     function );
347
348
0
    goto on_error;
349
0
  }
350
0
  if( memory_copy(
351
0
       internal_multi_string->data,
352
0
       data,
353
0
       data_size ) == NULL )
354
0
  {
355
0
    libcerror_error_set(
356
0
     error,
357
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
358
0
     LIBCERROR_MEMORY_ERROR_COPY_FAILED,
359
0
     "%s: unable to copy data.",
360
0
     function );
361
362
0
    goto on_error;
363
0
  }
364
0
  internal_multi_string->data_size = data_size;
365
366
0
  if( number_of_strings > 0 )
367
0
  {
368
0
    internal_multi_string->strings = (uint8_t **) memory_allocate(
369
0
                                                   sizeof( uint8_t * ) * number_of_strings );
370
371
0
    if( internal_multi_string->strings == NULL )
372
0
    {
373
0
      libcerror_error_set(
374
0
       error,
375
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
376
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
377
0
       "%s: unable to create strings.",
378
0
       function );
379
380
0
      goto on_error;
381
0
    }
382
0
    internal_multi_string->string_sizes = (size_t *) memory_allocate(
383
0
                                                      sizeof( size_t ) * number_of_strings );
384
385
0
    if( internal_multi_string->string_sizes == NULL )
386
0
    {
387
0
      libcerror_error_set(
388
0
       error,
389
0
       LIBCERROR_ERROR_DOMAIN_MEMORY,
390
0
       LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
391
0
       "%s: unable to create string sizes.",
392
0
       function );
393
394
0
      goto on_error;
395
0
    }
396
0
    data_offset = 0;
397
398
0
    while( data_offset < data_size )
399
0
    {
400
0
      string_start = &( ( internal_multi_string->data )[ data_offset ] );
401
0
      string_size  = 0;
402
403
0
      while( data_offset <= ( data_size - 2 ) )
404
0
      {
405
0
        string_size += 2;
406
407
0
        if( ( data[ data_offset ] == 0 )
408
0
         && ( data[ data_offset + 1 ] == 0 ) )
409
0
        {
410
0
          data_offset += 2;
411
412
0
          break;
413
0
        }
414
0
        data_offset += 2;
415
0
      }
416
0
      if( ( string_index < 0 )
417
0
       || ( string_index >= number_of_strings ) )
418
0
      {
419
0
        libcerror_error_set(
420
0
         error,
421
0
         LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
422
0
         LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
423
0
         "%s: invalid string index value out of bounds.",
424
0
         function );
425
426
0
        goto on_error;
427
0
      }
428
0
      internal_multi_string->strings[ string_index ]      = string_start;
429
0
      internal_multi_string->string_sizes[ string_index ] = string_size;
430
431
0
      string_index++;
432
433
0
      if( string_index >= number_of_strings )
434
0
      {
435
0
        break;
436
0
      }
437
0
    }
438
0
  }
439
0
  internal_multi_string->number_of_strings = number_of_strings;
440
441
0
  return( 1 );
442
443
0
on_error:
444
0
  if( internal_multi_string->string_sizes != NULL )
445
0
  {
446
0
    memory_free(
447
0
     internal_multi_string->string_sizes );
448
449
0
    internal_multi_string->string_sizes = NULL;
450
0
  }
451
0
  if( internal_multi_string->strings != NULL )
452
0
  {
453
0
    memory_free(
454
0
     internal_multi_string->strings );
455
456
0
    internal_multi_string->strings = NULL;
457
0
  }
458
0
  internal_multi_string->number_of_strings = 0;
459
460
0
  if( internal_multi_string->data != NULL )
461
0
  {
462
0
    memory_free(
463
0
     internal_multi_string->data );
464
465
0
    internal_multi_string->data = NULL;
466
0
  }
467
0
  internal_multi_string->data_size = 0;
468
469
0
  return( -1 );
470
0
}
471
472
/* Retrieves the number of strings
473
 * Returns 1 if successful or -1 on error
474
 */
475
int libregf_multi_string_get_number_of_strings(
476
     libregf_multi_string_t *multi_string,
477
     int *number_of_strings,
478
     libcerror_error_t **error )
479
0
{
480
0
  libregf_internal_multi_string_t *internal_multi_string = NULL;
481
0
  static char *function                                  = "libregf_multi_string_get_number_of_strings";
482
483
0
  if( multi_string == NULL )
484
0
  {
485
0
    libcerror_error_set(
486
0
     error,
487
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
488
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
489
0
     "%s: invalid multi string.",
490
0
     function );
491
492
0
    return( -1 );
493
0
  }
494
0
  internal_multi_string = (libregf_internal_multi_string_t *) multi_string;
495
496
0
  if( number_of_strings == NULL )
497
0
  {
498
0
    libcerror_error_set(
499
0
     error,
500
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
501
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
502
0
     "%s: invalid number of strings.",
503
0
     function );
504
505
0
    return( -1 );
506
0
  }
507
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
508
0
  if( libcthreads_read_write_lock_grab_for_read(
509
0
       internal_multi_string->read_write_lock,
510
0
       error ) != 1 )
511
0
  {
512
0
    libcerror_error_set(
513
0
     error,
514
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
515
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
516
0
     "%s: unable to grab read/write lock for reading.",
517
0
     function );
518
519
0
    return( -1 );
520
0
  }
521
0
#endif
522
0
  *number_of_strings = internal_multi_string->number_of_strings;
523
524
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
525
0
  if( libcthreads_read_write_lock_release_for_read(
526
0
       internal_multi_string->read_write_lock,
527
0
       error ) != 1 )
528
0
  {
529
0
    libcerror_error_set(
530
0
     error,
531
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
532
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
533
0
     "%s: unable to release read/write lock for reading.",
534
0
     function );
535
536
0
    return( -1 );
537
0
  }
538
0
#endif
539
0
  return( 1 );
540
0
}
541
542
/* Retrieves the UTF-8 string size of a specific string
543
 * The returned size includes the end of string character
544
 * Returns 1 if successful or -1 on error
545
 */
546
int libregf_multi_string_get_utf8_string_size(
547
     libregf_multi_string_t *multi_string,
548
     int string_index,
549
     size_t *utf8_string_size,
550
     libcerror_error_t **error )
551
0
{
552
0
  libregf_internal_multi_string_t *internal_multi_string = NULL;
553
0
  static char *function                                  = "libregf_multi_string_get_utf8_string_size";
554
0
  int result                                             = 1;
555
556
0
  if( multi_string == NULL )
557
0
  {
558
0
    libcerror_error_set(
559
0
     error,
560
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
561
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
562
0
     "%s: invalid multi string.",
563
0
     function );
564
565
0
    return( -1 );
566
0
  }
567
0
  internal_multi_string = (libregf_internal_multi_string_t *) multi_string;
568
569
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
570
0
  if( libcthreads_read_write_lock_grab_for_read(
571
0
       internal_multi_string->read_write_lock,
572
0
       error ) != 1 )
573
0
  {
574
0
    libcerror_error_set(
575
0
     error,
576
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
577
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
578
0
     "%s: unable to grab read/write lock for reading.",
579
0
     function );
580
581
0
    return( -1 );
582
0
  }
583
0
#endif
584
0
  if( ( string_index < 0 )
585
0
   || ( string_index >= internal_multi_string->number_of_strings ) )
586
0
  {
587
0
    libcerror_error_set(
588
0
     error,
589
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
590
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
591
0
     "%s: invalid string index value out of bounds.",
592
0
     function );
593
594
0
    result = -1;
595
0
  }
596
0
  else if( libuna_utf8_string_size_from_utf16_stream(
597
0
            internal_multi_string->strings[ string_index ],
598
0
            internal_multi_string->string_sizes[ string_index ],
599
0
            LIBUNA_ENDIAN_LITTLE,
600
0
            utf8_string_size,
601
0
            error ) != 1 )
602
0
  {
603
0
    libcerror_error_set(
604
0
     error,
605
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
606
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
607
0
     "%s: unable to determine UTF-8 string size.",
608
0
     function );
609
610
0
    result = -1;
611
0
  }
612
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
613
0
  if( libcthreads_read_write_lock_release_for_read(
614
0
       internal_multi_string->read_write_lock,
615
0
       error ) != 1 )
616
0
  {
617
0
    libcerror_error_set(
618
0
     error,
619
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
620
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
621
0
     "%s: unable to release read/write lock for reading.",
622
0
     function );
623
624
0
    return( -1 );
625
0
  }
626
0
#endif
627
0
  return( result );
628
0
}
629
630
/* Retrieves the UTF-8 encoded string of a specific string
631
 * The size should include the end of string character
632
 * Returns 1 if successful or -1 on error
633
 */
634
int libregf_multi_string_get_utf8_string(
635
     libregf_multi_string_t *multi_string,
636
     int string_index,
637
     uint8_t *utf8_string,
638
     size_t utf8_string_size,
639
     libcerror_error_t **error )
640
0
{
641
0
  libregf_internal_multi_string_t *internal_multi_string = NULL;
642
0
  static char *function                                  = "libregf_multi_string_get_utf8_string";
643
0
  int result                                             = 1;
644
645
0
  if( multi_string == NULL )
646
0
  {
647
0
    libcerror_error_set(
648
0
     error,
649
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
650
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
651
0
     "%s: invalid multi string.",
652
0
     function );
653
654
0
    return( -1 );
655
0
  }
656
0
  internal_multi_string = (libregf_internal_multi_string_t *) multi_string;
657
658
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
659
0
  if( libcthreads_read_write_lock_grab_for_read(
660
0
       internal_multi_string->read_write_lock,
661
0
       error ) != 1 )
662
0
  {
663
0
    libcerror_error_set(
664
0
     error,
665
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
666
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
667
0
     "%s: unable to grab read/write lock for reading.",
668
0
     function );
669
670
0
    return( -1 );
671
0
  }
672
0
#endif
673
0
  if( ( string_index < 0 )
674
0
   || ( string_index >= internal_multi_string->number_of_strings ) )
675
0
  {
676
0
    libcerror_error_set(
677
0
     error,
678
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
679
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
680
0
     "%s: invalid string index value out of bounds.",
681
0
     function );
682
683
0
    result = -1;
684
0
  }
685
0
  else if( libuna_utf8_string_copy_from_utf16_stream(
686
0
            utf8_string,
687
0
            utf8_string_size,
688
0
            internal_multi_string->strings[ string_index ],
689
0
            internal_multi_string->string_sizes[ string_index ],
690
0
            LIBUNA_ENDIAN_LITTLE,
691
0
            error ) != 1 )
692
0
  {
693
0
    libcerror_error_set(
694
0
     error,
695
0
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
696
0
     LIBCERROR_CONVERSION_ERROR_GENERIC,
697
0
     "%s: unable to set UTF-8 string.",
698
0
     function );
699
700
0
    result = -1;
701
0
  }
702
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
703
0
  if( libcthreads_read_write_lock_release_for_read(
704
0
       internal_multi_string->read_write_lock,
705
0
       error ) != 1 )
706
0
  {
707
0
    libcerror_error_set(
708
0
     error,
709
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
710
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
711
0
     "%s: unable to release read/write lock for reading.",
712
0
     function );
713
714
0
    return( -1 );
715
0
  }
716
0
#endif
717
0
  return( result );
718
0
}
719
720
/* Retrieves the UTF-16 string size of a specific string
721
 * The returned size includes the end of string character
722
 * Returns 1 if successful or -1 on error
723
 */
724
int libregf_multi_string_get_utf16_string_size(
725
     libregf_multi_string_t *multi_string,
726
     int string_index,
727
     size_t *utf16_string_size,
728
     libcerror_error_t **error )
729
0
{
730
0
  libregf_internal_multi_string_t *internal_multi_string = NULL;
731
0
  static char *function                                  = "libregf_multi_string_get_utf16_string_size";
732
0
  int result                                             = 1;
733
734
0
  if( multi_string == NULL )
735
0
  {
736
0
    libcerror_error_set(
737
0
     error,
738
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
739
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
740
0
     "%s: invalid multi string.",
741
0
     function );
742
743
0
    return( -1 );
744
0
  }
745
0
  internal_multi_string = (libregf_internal_multi_string_t *) multi_string;
746
747
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
748
0
  if( libcthreads_read_write_lock_grab_for_read(
749
0
       internal_multi_string->read_write_lock,
750
0
       error ) != 1 )
751
0
  {
752
0
    libcerror_error_set(
753
0
     error,
754
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
755
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
756
0
     "%s: unable to grab read/write lock for reading.",
757
0
     function );
758
759
0
    return( -1 );
760
0
  }
761
0
#endif
762
0
  if( ( string_index < 0 )
763
0
   || ( string_index >= internal_multi_string->number_of_strings ) )
764
0
  {
765
0
    libcerror_error_set(
766
0
     error,
767
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
768
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
769
0
     "%s: invalid string index value out of bounds.",
770
0
     function );
771
772
0
    result = -1;
773
0
  }
774
0
  else if( libuna_utf16_string_size_from_utf16_stream(
775
0
            internal_multi_string->strings[ string_index ],
776
0
            internal_multi_string->string_sizes[ string_index ],
777
0
            LIBUNA_ENDIAN_LITTLE,
778
0
            utf16_string_size,
779
0
            error ) != 1 )
780
0
  {
781
0
    libcerror_error_set(
782
0
     error,
783
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
784
0
     LIBCERROR_RUNTIME_ERROR_GET_FAILED,
785
0
     "%s: unable to determine UTF-16 string size.",
786
0
     function );
787
788
0
    result = -1;
789
0
  }
790
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
791
0
  if( libcthreads_read_write_lock_release_for_read(
792
0
       internal_multi_string->read_write_lock,
793
0
       error ) != 1 )
794
0
  {
795
0
    libcerror_error_set(
796
0
     error,
797
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
798
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
799
0
     "%s: unable to release read/write lock for reading.",
800
0
     function );
801
802
0
    return( -1 );
803
0
  }
804
0
#endif
805
0
  return( result );
806
0
}
807
808
/* Retrieves the UTF-16 encoded string of a specific string
809
 * The size should include the end of string character
810
 * Returns 1 if successful or -1 on error
811
 */
812
int libregf_multi_string_get_utf16_string(
813
     libregf_multi_string_t *multi_string,
814
     int string_index,
815
     uint16_t *utf16_string,
816
     size_t utf16_string_size,
817
     libcerror_error_t **error )
818
0
{
819
0
  libregf_internal_multi_string_t *internal_multi_string = NULL;
820
0
  static char *function                                  = "libregf_multi_string_get_utf16_string";
821
0
  int result                                             = 1;
822
823
0
  if( multi_string == NULL )
824
0
  {
825
0
    libcerror_error_set(
826
0
     error,
827
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
828
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
829
0
     "%s: invalid multi string.",
830
0
     function );
831
832
0
    return( -1 );
833
0
  }
834
0
  internal_multi_string = (libregf_internal_multi_string_t *) multi_string;
835
836
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
837
0
  if( libcthreads_read_write_lock_grab_for_read(
838
0
       internal_multi_string->read_write_lock,
839
0
       error ) != 1 )
840
0
  {
841
0
    libcerror_error_set(
842
0
     error,
843
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
844
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
845
0
     "%s: unable to grab read/write lock for reading.",
846
0
     function );
847
848
0
    return( -1 );
849
0
  }
850
0
#endif
851
0
  if( ( string_index < 0 )
852
0
   || ( string_index >= internal_multi_string->number_of_strings ) )
853
0
  {
854
0
    libcerror_error_set(
855
0
     error,
856
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
857
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
858
0
     "%s: invalid string index value out of bounds.",
859
0
     function );
860
861
0
    result = -1;
862
0
  }
863
0
  else if( libuna_utf16_string_copy_from_utf16_stream(
864
0
            utf16_string,
865
0
            utf16_string_size,
866
0
            internal_multi_string->strings[ string_index ],
867
0
            internal_multi_string->string_sizes[ string_index ],
868
0
            LIBUNA_ENDIAN_LITTLE,
869
0
            error ) != 1 )
870
0
  {
871
0
    libcerror_error_set(
872
0
     error,
873
0
     LIBCERROR_ERROR_DOMAIN_CONVERSION,
874
0
     LIBCERROR_CONVERSION_ERROR_GENERIC,
875
0
     "%s: unable to set UTF-16 string.",
876
0
     function );
877
878
0
    result = -1;
879
0
  }
880
0
#if defined( HAVE_LIBREGF_MULTI_THREAD_SUPPORT )
881
0
  if( libcthreads_read_write_lock_release_for_read(
882
0
       internal_multi_string->read_write_lock,
883
0
       error ) != 1 )
884
0
  {
885
0
    libcerror_error_set(
886
0
     error,
887
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
888
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
889
0
     "%s: unable to release read/write lock for reading.",
890
0
     function );
891
892
0
    return( -1 );
893
0
  }
894
0
#endif
895
0
  return( result );
896
0
}
897